Android动画学习(六)之View揭露效果和SurfaceView实现动画
View揭露效果
概述
当显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。ViewAnimationUtils.createCircularReveal() 方法让您能够为裁剪区域添加动画以揭露或隐藏视图。这是Android5.0推出的新的动画框架,可以给View做一个揭露效果。 使用非常简单。
官网介绍:
如果要使用此效果揭露之前不可见的视图:
// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
如果要使用此效果隐藏之前可见的视图:
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
源码解析:
public static Animator createCircularReveal(View view,
int centerX, int centerY, float startRadius, float endRadius)
参数说明:
view:控件
centerX和centerY :中心点坐标
startRadius:开始半径
endRadius:结束半径
示例代码:
/**
* Android5.0推出的新的动画框架,可以给View做一个揭露效果
*
* @author ZD
* created at 2017/7/14 10:17
* description:
*/
public class CircularReveralActivity extends AppCompatActivity {
private ImageView imageView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_circularepeveral);
imageView = (ImageView) findViewById(R.id.iv_CircularReveral);
}
/**
* 五个参数分别是View,中心点坐标,开始半径,结束半径。通过这五个参数的配合,我们可以做出很多不同的效果。
* @param v
*/
public void CircularReveral(View v) {
Animator anim = ViewAnimationUtils.createCircularReveal(imageView, imageView.getWidth() / 2, imageView.getHeight() / 2, imageView.getWidth(), 0);
anim.setDuration(2000);
anim.start();
}
}
示例效果:
SurfaceView实现动画
概述:
SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置.
Vew 的绘图机制存在如下缺陷:
- View 缺乏双缓冲机制。
- 当程序需要更新 View 上的图片时,程序必须重绘 View 上显示的整张图片。
- 新线程无法直接更新 View 组件。
SurfaceView 与普通 View 还有一个重要的区别: View 的绘图必须在当前 UI 线程中进行——这也是前面程序需要更新 View 组件时总要采用 Handler 处理的原因;但 SurfaceView 就不会存在这个问题,因此 SurfaceView 的绘图是由 SurfaceHolder 来完成的。对于 View 组件,如果程序需要花较长的时间来更新绘图,那么主 UI 线程将会被阻塞,无法响应用户的任何动作;而 SurfaceHolder 则会启用新的线程去更新 SurfaceView 的绘制,因
此不会阻塞主 UI 线程。 、
一般来说,如果程序或游戏界面的动画元素较多,而且很多动画元素的移动都需要通定时器来控制,就可以考虑使用 SurfaceView ,而不是 View 。
SurfaceView绘图机制:
Surface View —般会与SurfaceHolder结合使用,SurfaceHolder用于向与之关联的SurfaceView上绘图,调用Surface View的getHolder()方法即可获取SurfaceView关联的SurfaceHolder。
SurfaceHolder提供了如下方法来获取Canvas对象。
Canvas l〇ckCanvas():锁定整个 SurfaceView 对象,获取该 SurfaceView 上的 Canvas。
Canvas lockCanvas(Rect dirty) : 锁 定 SurfaceView 上 Rect 划分的区域,获取该
SurfaceView 上的 Canvas。
当对同一个SurfaceView调用上面两个方法时,两个方法所返回的是同一个Canvas对象。但当程序调用第二个方法获取指定区域的Canvas时,SurfaceView将只对Rect所“圈”出来的区域进行更新,通过这种方式可以提高画面的更新速度。当通过lockCanvas()获取了指定SurfaceView上的Canvas之后,接下来程序就可以调用
Canvas进行绘图了,Canvas绘图完成后通过如下方法来释放绘图、提交所绘制的图形。
- unlockCanvasAndPost(canvas)
需要指出的是,当调用SurfaceHolder的unlockCanvasAndPost()方法之后,该方法之前所绘制的图形还处于缓冲区中,下一次lockCanvasO方法锁定的区域可能会“遮挡”它。
SurfaceView绘图示例——示波器代码:
java代码:
public class SurfaceViewActivity extends AppCompatActivity {
private SurfaceHolder holder;
private Paint paint;
final int HEIGHT = 320;
final int WIDTH = 768;
final int X_OFFSET = 5;
private int cx = X_OFFSET;
// 实际的Y轴的位置
int centerY = HEIGHT / 2;
Timer timer = new Timer();
TimerTask task = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_surface_view);
TextView textView = (TextView) findViewById(R.id.tv_title);
//设置标题
textView.setText("SurfaceView示波器");
final SurfaceView surface = (SurfaceView)
findViewById(R.id.show);
// 初始化SurfaceHolder对象
holder = surface.getHolder();
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
Button sin = (Button)findViewById(R.id.sin);
Button cos = (Button)findViewById(R.id.cos);
OnClickListener listener = (new OnClickListener()
{
@Override
public void onClick(final View source)
{
drawBack(holder);
cx = X_OFFSET;
if(task != null)
{
task.cancel();
}
task = new TimerTask()
{
public void run()
{
int cy = source.getId() == R.id.sin ? centerY
- (int)(100 * Math.sin((cx - 5) * 2
* Math.PI / 150))
: centerY - (int)(100 * Math.cos ((cx - 5)
* 2 * Math.PI / 150));
Canvas canvas = holder.lockCanvas(new Rect(cx ,
cy - 2 , cx + 2, cy + 2));
canvas.drawPoint(cx , cy , paint);
cx ++;
if (cx > WIDTH)
{
task.cancel();
task = null;
}
holder.unlockCanvasAndPost(canvas);
}
};
timer.schedule(task , 0 , 30);
}
});
sin.setOnClickListener(listener);
cos.setOnClickListener(listener);
holder.addCallback(new SurfaceHolder.Callback()
{
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height)
{
drawBack(holder);
}
@Override
public void surfaceCreated(final SurfaceHolder myHolder){ }
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
timer.cancel();
}
});
}
private void drawBack(SurfaceHolder holder)
{
Canvas canvas = holder.lockCanvas();
// 绘制白色背景
canvas.drawColor(Color.WHITE);
Paint p = new Paint();
p.setColor(Color.BLACK);
p.setStrokeWidth(2);
// 绘制坐标轴
canvas.drawLine(X_OFFSET , centerY , WIDTH , centerY , p);
canvas.drawLine(X_OFFSET , 40 , X_OFFSET , HEIGHT , p);
holder.unlockCanvasAndPost(canvas);
holder.lockCanvas(new Rect(0 , 0 , 0 , 0));
holder.unlockCanvasAndPost(canvas);
}
}
Xml中引用SurfaceView
<SurfaceView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
效果:
总结
View动画到这篇博客已经完全学习完了。下一篇介绍转场动画。
写博客是为了帮助开发者学习使用技术,同时巩固自己所学技术。如果此篇博客有助于您的学习,那是我的荣幸!如果此篇博客有任何瑕疵,请多多指教!在此感谢您的学习和指教!