<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>润物无声 &#187; ViewOverlay</title>
	<atom:link href="http://blog.zhourunsheng.com/tag/viewoverlay/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.zhourunsheng.com</link>
	<description>天空一朵雨做的云</description>
	<lastBuildDate>Sat, 08 May 2021 05:17:21 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.41</generator>
	<item>
		<title>Android动画设计之ViewOverlay</title>
		<link>http://blog.zhourunsheng.com/2013/08/android%e5%8a%a8%e7%94%bb%e8%ae%be%e8%ae%a1%e4%b9%8bviewoverlay/</link>
		<comments>http://blog.zhourunsheng.com/2013/08/android%e5%8a%a8%e7%94%bb%e8%ae%be%e8%ae%a1%e4%b9%8bviewoverlay/#comments</comments>
		<pubDate>Thu, 22 Aug 2013 02:38:06 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[ViewOverlay]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1813</guid>
		<description><![CDATA[<p>什么是ViewOverlay？ ViewOverlay is a class that we can find [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/android%e5%8a%a8%e7%94%bb%e8%ae%be%e8%ae%a1%e4%b9%8bviewoverlay/">Android动画设计之ViewOverlay</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<h2>什么是ViewOverlay？</h2>
<p><a href="http://developer.android.com/reference/android/view/ViewOverlay.html">ViewOverlay</a> is a class that we can find in Android since its version <a href="http://developer.android.com/about/versions/android-4.3.html">4.3</a> (API version 18) that provides a transparent layer on top of a <a href="http://developer.android.com/reference/android/view/View.html">View</a>, to which you can add visual content and that does not affect the layout hierarchy.</p>
<p>It always has the same size and position as its host view, allowing you to add content over that view.<span id="more-1813"></span></p>
<h2>运行效果</h2>
<p><img class="alignnone" alt="" src="http://blog.zhourunsheng.com/wp-content/uploads/2013/08/vo-all.gif" width="475" height="686" /></p>
<p>红色部分：使用了 按钮的 parent-parent layout (the main, first-level, layout) ViewGroupOverlay，所以可以穿越整个画面。</p>
<p>橙色部分：没有使用ViewOverlay技术，所以按钮的动画只限定于它的父窗口部分。</p>
<p>绿色部分：结合使用了两种技术，首先是渐变消失，alpha animation from 1f to 0f，然后放在橙色 non-parent ViewOverlay (the orange layout)中，后段动画仅限制与橙色部分。</p>
<h2>使用方法</h2>
<p>You just have to call the <a href="http://developer.android.com/reference/android/view/View.html#getOverlay()">getOverlay()</a> method from any View of your app to get its<a href="http://developer.android.com/reference/android/view/ViewOverlay.html">ViewOverlay</a>, or a <a href="http://developer.android.com/reference/android/view/ViewGroupOverlay.html#add(android.view.View)">ViewGroupOverlay</a> if you are calling this method from some<a href="http://developer.android.com/reference/android/view/ViewGroup.html">ViewGroup</a> object, but both of them uses the same concept.</p>
<p>Once you got it, you can add any View or Drawable that you want to show in this overlay calling <a href="http://developer.android.com/reference/android/view/ViewOverlay.html#add(android.graphics.drawable.Drawable)">add(Drawable drawable)</a> method on <a href="http://developer.android.com/reference/android/view/ViewOverlay.html">ViewOverlay</a>, or <a href="http://developer.android.com/reference/android/view/ViewGroupOverlay.html#add(android.view.View)">add(View view)</a>on <a href="http://developer.android.com/reference/android/view/ViewGroupOverlay.html#add(android.view.View)">ViewGroupOverlay</a>.</p>
<p>ViewOverlay API is so simple, aside from <a href="http://developer.android.com/reference/android/view/ViewOverlay.html#add(android.graphics.drawable.Drawable)">add(Drawable drawable)</a>, we can also find<a href="http://developer.android.com/reference/android/view/ViewOverlay.html#clear()">clear()</a> and <a href="http://developer.android.com/reference/android/view/ViewOverlay.html#remove(android.graphics.drawable.Drawable)">remove(Drawable drawable)</a>. These are the only methods that we have to use to handle the views that we move to our ViewOverlays.</p>
<h2>优势</h2>
<p>Well, for now everything that I came up to my mind to do with this new API can be done using RelativeLayout and  a bit of <b>tricky &amp; ugly code</b>. But this lets us to do that things in a friendly way.</p>
<p>Essentially, <b>this component is visual-only</b>, so views attached to a ViewOverlay will not respond to any touch or tap event. ViewOverlay mechanism was conceived to be used combined with stuff like <b>animations</b>.</p>
<p><b>Using ViewOverlays we can animate views through other layouts in view hierarchy, even if they are not any of its parents.</b></p>
<p>So when some of these animations ends, we should have to call <a href="http://developer.android.com/reference/android/view/ViewOverlay.html#clear()">clear()</a> or<a href="http://developer.android.com/reference/android/view/ViewOverlay.html#remove(android.graphics.drawable.Drawable)">remove(Drawable drawable)</a> methods, to remove the view from our ViewOverlay to keep it clean and avoid memory leaks.</p>
<h2>使用限制</h2>
<p>Yeah, but…</p>
<ul>
<li>This is<b> only for API 18+</b>, although we hope it will be backported at some support library in the near future.</li>
<li>Right now, there is not a single example.</li>
</ul>
<p>We can not do anything to solve the first point, but today we have been playing with this new stuff to try to understand how it works. So…</p>
<p>程序源码<br />
1.  界面布局 activity_main.xml</p>
<pre>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" &gt;

&lt;FrameLayout
android:id="@+id/redContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_red_light" &gt;

&lt;Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="ViewOverlay" /&gt;
&lt;/FrameLayout&gt;

&lt;FrameLayout
android:id="@+id/greenContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_orange_light" &gt;

&lt;Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Normal animator" /&gt;
&lt;/FrameLayout&gt;

&lt;FrameLayout
android:id="@+id/orangeContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_green_light" &gt;

&lt;Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="ViewOverlay on other parent" /&gt;
&lt;/FrameLayout&gt;

&lt;/LinearLayout&gt;</pre>
<p>2. MainActivity.java</p>
<pre>package cat.lafosca.viewoverlaytest;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.Button;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		viewsSetup();
	}

	private void viewsSetup() {
		setContentView(R.layout.activity_main);

		final Button button = (Button) findViewById(R.id.button);

		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// Our button is added to the parent of its parent, the most top-level layout
				final ViewGroup container = (ViewGroup) button.getParent().getParent();
				container.getOverlay().add(button);

				ObjectAnimator anim = ObjectAnimator.ofFloat(button, "translationY", container.getHeight());
				ObjectAnimator rotate = ObjectAnimator.ofFloat(button, "rotation", 0, 360);
				rotate.setRepeatCount(Animation.INFINITE);
				rotate.setRepeatMode(Animation.REVERSE);
				rotate.setDuration(350);

				/*
				 * Button needs to be removed after animation ending
				 * When we have added the view to the ViewOverlay, 
				 * it was removed from its original parent.
				 */
				anim.addListener(new AnimatorListener() {

					@Override
					public void onAnimationStart(Animator arg0) {
					}

					@Override
					public void onAnimationRepeat(Animator arg0) {
					}

					@Override
					public void onAnimationEnd(Animator arg0) {
						container.getOverlay().remove(button);
					}

					@Override
					public void onAnimationCancel(Animator arg0) {
						container.getOverlay().remove(button);
					}
				});

				anim.setDuration(2000);

				AnimatorSet set = new AnimatorSet();
				set.playTogether(anim, rotate);
				set.start();
			}
		});

		final Button button2 = (Button) findViewById(R.id.button2);
		button2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// Normal animation, we only see it when is animating in its original layout container.
				final ViewGroup container = (ViewGroup) button2.getParent().getParent();
				ObjectAnimator anim = ObjectAnimator.ofFloat(button2, "translationY", -container.getHeight());
				anim.setDuration(2000);
				anim.start();
			}
		});

		final Button button3 = (Button) findViewById(R.id.button3);
		button3.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				ObjectAnimator fadeOut = ObjectAnimator.ofFloat(button3, "alpha", 1f, 0f);
				fadeOut.setDuration(500);

				/* 
				 * Here we add our button to center layout's ViewGroupOverlay
				 * when first fade-out animation ends.
				 */
				final ViewGroup container = (ViewGroup) button2.getParent();
				final ObjectAnimator anim = ObjectAnimator.ofFloat(button3, "translationY", -container.getHeight() * 2);
				anim.setDuration(2000);

				anim.addListener(new AnimatorListener() {

					@Override
					public void onAnimationStart(Animator animation) { }

					@Override
					public void onAnimationRepeat(Animator animation) { }

					@Override
					public void onAnimationEnd(Animator animation) {
						container.getOverlay().remove(button3);
					}

					@Override
					public void onAnimationCancel(Animator animation) {
						container.getOverlay().remove(button3);
					}
				});

				fadeOut.addListener(new AnimatorListener() {

					@Override
					public void onAnimationStart(Animator arg0) {
					}

					@Override
					public void onAnimationRepeat(Animator arg0) {
					}

					@Override
					public void onAnimationEnd(Animator arg0) {
						container.getOverlay().add(button3);
						button3.setAlpha(1f);
						anim.start();
					}

					@Override
					public void onAnimationCancel(Animator arg0) {
						container.getOverlay().add(button3);
						button3.setAlpha(1f);
						anim.start();
					}
				});

				fadeOut.start();
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.action_reset) { 
			viewsSetup();
		}
		return super.onOptionsItemSelected(item);
	}

}</pre>
<p>完整代码下载：You can download and check our project from <a href="http://www.lafosca.cat/wp-content/uploads/2013/08/ViewOverlayTest.zip">right here</a>.</p>
<p>参照文章：<a href="http://www.lafosca.cat/viewoverlay-in-android/">http://www.lafosca.cat/viewoverlay-in-android/</a></p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/android%e5%8a%a8%e7%94%bb%e8%ae%be%e8%ae%a1%e4%b9%8bviewoverlay/">Android动画设计之ViewOverlay</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2013/08/android%e5%8a%a8%e7%94%bb%e8%ae%be%e8%ae%a1%e4%b9%8bviewoverlay/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
