TranslateAnimation
使用TranslateAnimation操作控件位移比较常用,但如果被操作的对象需要发生交互,就有可能出现问题。因为控件执行完毕TA动画后,其可视的位置并不是物理位置,实际其物理位置没有发生变化。如果此时交互(如点击事件),会发生点击看到的控件没反应,而点击动画前的位置有反应。
处理这个问题,只要在动画事件结束后重写布局一下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
final View iv = findViewById(R.id.iv); // 参数:起点x float fromXDelta, x轴距离 float toXDelta, 起点y float fromYDelta, y轴距离 float toYDelta TranslateAnimation ta = new TranslateAnimation(20, 100, 30, 100); // 移动到x为120,y为130的点 ta.setDuration(500); // 时长 ta.setInterpolator(new AccelerateInterpolator()); // 加速器 ta.setFillAfter(true); // 保持动画结束状态 ta.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // 父容器布局属性 LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) iv.getLayoutParams(); Log.e("anim", "width:" + params.width + "," + iv.getWidth() + ",height"+params.height); iv.clearAnimation(); Log.e("anim", "iv.getx:" + iv.getX()); iv.layout(120, 130, iv.getWidth()+120, iv.getHeight()+130); // 重写绘制控件相对于父容器的所占空间,左上角xy,右下角rb坐标 iv.invalidate(); } }); iv.startAnimation(ta); |
一般使用TA制作抽屉动画,都在移动整个屏幕宽度的距离。但如果移动距离不是整个屏幕宽度,还要进行交互,当继续使用TA进行复位时,有可能会出现闪屏的现象(当复位时,TA会将控件先移出屏幕,再执行动画移动),愚尚未解决。
Scroller
另一种抽屉动画实现是使用Scroller,关于此兄,搜索引擎可详查。
使用流程一般是:
1)自定义一个布局,如public class ScrollerLinearLyt extends LinearLayout
2)在其中定有一个Scroller属性,private Scroller scroller;,
并初始化
1 2 3 4 5 6 7 |
public ScrollerLinearLyt(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(context); } |
3)自定义一个执行动画的方法
1 2 3 4 5 6 7 8 9 10 |
public void doScrollTo(int dx, int duration) { // 开始滑动(x轴出发点,y轴出发点,x轴距离,y轴距离,时长) scroller.startScroll(getScrollX(), getScrollY(), dx, getScrollY(), duration); // 刷新布局 invalidate(); } |
4)重写一个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * 滑动过程中持续调用此方法。此方法代码取于网络 */ @Override public void computeScroll() { // 当滑动执行完毕 if (scroller.computeScrollOffset()) { int oldX = getScrollX(); // 本布局停止后的位置 int oldY = getScrollY(); int x = scroller.getCurrX(); // 获取Scroller停止后当前水平位置 int y = scroller.getCurrY(); if (oldX != x || oldY != y) { // 个人理解为坐标 scrollTo(x, y); // 将View中内容滑动到相应的位置,参考的坐标系原点为parent View的左上角 } invalidate(); } } |
5)使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 首先实例化使用自定义布局类在本activity中注册的控件 final ScrollerLinearLyt lltop = (ScrollerLinearLyt) findViewById(R.id.lltop_container_hmaty); // 得到屏幕宽度 Point point = new Point(); getActivity().getWindow().getWindowManager().getDefaultDisplay().getSize(point); // 目标移动距离 final int xOffset = point.x / 4 * 3; // 此boolean变量,当抽屉关闭时为false,抽屉打开时为true if (!isHmAtyGone) { // 如果抽屉关着,那么执行抽屉动画 isHmAtyGone = true; lltop.doScrollTo( - xOffset, 500); } else { // 如果抽屉开着,执行复位动画 isHmAtyGone = false; lltop.doScrollTo( xOffset, 500); } |
Scroller和Touch事件的结合
类似于SlidingMenu的效果,以及SlidingUI相关。随着手指的滑动执行抽屉动画。一个的也是自定义一个布局类,在其中处理touch事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
package com.cuiweiyou.view; import android.content.Context; import android.graphics.Point; import android.graphics.PointF; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Scroller; import com.cuiweiyou.activity.HomeActivity; /** * ImageView只能对其中src指定的图片有效<br/> * 一般都是重写布局,对其中子元素全部有效 * * @author cuiweiyou.com * */ public class ScrollerLinearLyt extends LinearLayout { /** 滑动器 **/ private Scroller scroller; /** 设置容器Aty的抽屉状态接口。第一次点击打开抽屉时初始化 **/ /** touch滑动时手指按下的点 **/ private PointF downPoint; /** 抽屉左侧 **/ private int xOffset; /** 随时保持手指上次移动的点 **/ private PointF tmpPoint; /** 手机屏幕宽x-高y **/ Point point = new Point(); public ScrollerLinearLyt(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(context); } /** * 自定义方法:平滑移动本布局<br/> * 用于按钮点击时执行滑动 * * @param dx x轴移动距离 * @param duration 时长 * cuiweiyou.com */ public void doScrollTo(int dx, int duration) { // 开始滑动(x轴出发点,y轴出发点,x轴距离,y轴距离,时长) scroller.startScroll(getScrollX(), getScrollY(), dx, getScrollY(), duration); // 刷新布局 invalidate(); } /** * 滑动过程中持续调用此方法 * cuiweiyou.com */ @Override public void computeScroll() { // 当滑动执行完毕 if (scroller.computeScrollOffset()) { int oldX = getScrollX(); // 本布局停止后的位置 int oldY = getScrollY(); int x = scroller.getCurrX(); // 获取Scroller停止后当前水平位置 int y = scroller.getCurrY(); if (oldX != x || oldY != y) { scrollTo(x, y); // 将View中内容滑动到相应的位置,参考的坐标系原点为parent View的左上角 } invalidate(); } } /** * Touch滑动事件处理<br/> * hmAty为null说明抽屉没有打开过,至少当前不少第一次打开状态<br/> * hmaty不为null,就须根据接口判断是不是打开。打开时处理touch事件 * cuiweiyou.com */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { // 第一次打开抽屉时才得到hmaty if(hmAty == null) return super.dispatchTouchEvent(ev); // 当手指按下 if(ev.getAction() == MotionEvent.ACTION_DOWN){ downPoint = new PointF(ev.getX(), ev.getY()); tmpPoint = new PointF(ev.getX(), ev.getY()); // 获取屏幕宽高 ((HomeActivity)hmAty).getWindow().getWindowManager().getDefaultDisplay().getSize(point); xOffset = point.x / 4 * 3; } // 当手指滑动 else if(ev.getAction() == MotionEvent.ACTION_MOVE){ PointF movePoint = new PointF(ev.getX(), ev.getY()); float distanceX = movePoint.x - tmpPoint.x; // 新位置发生的方向 if(getScrollX() < 0){ scrollBy((int)-distanceX, 0); // 相对移动 } else if (getScrollX() >= 0){ scrollTo(0, 0); // 目标移动 } invalidate(); tmpPoint = movePoint; } // 当手指拿起 else if(ev.getAction() == MotionEvent.ACTION_UP){ if(getScrollX() > -361){ scrollTo(0, 0); // 抽屉关闭,复位 } else { scrollTo((int) -540, 0); } invalidate(); } return super.dispatchTouchEvent(ev); } } |
尚有欠佳之处,望不吝赐教
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/1629.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设