安卓改变布局Y坐标实现位移动画

首先定义布局代码,这个可以i是安卓的任意控件,如:

 <LinearLayout
        android:id="@+id/ll_push_register_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center_horizontal">
        <android.support.v7.widget.AppCompatImageView
            android:layout_width="29dp"
            android:layout_height="29dp"
            android:layout_gravity="center_vertical"
            android:scaleType="fitXY"
            android:src="@drawable/ic_down_push"/>
        <android.support.v7.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下拉展开签到"
            android:layout_gravity="center_vertical"
            android:gravity="center_vertical"
            android:textSize="13sp"
            android:textColor="@color/white"/>
    </LinearLayout>

下面是更改控件Y坐标的核心代码:

mPushRegisterLayout.postDelayed(new Runnable() { //等界面绘制完成后启动动画
            @Override
            public void run() {
                mPushRegisterLayout.setTag(R.string.isUp,false);
                mStartPosition = new Point((int)mPushRegisterLayout.getX(), (int) mPushRegisterLayout.getY());
                mHandler.sendEmptyMessageDelayed(START_PUSH_ANIMATION,1500);
            }
        },1000);

通过View的postDelayed()),开启一个子线程去延时发送一个消息去更改控件的Y坐标,更改位移坐标的代码如下:

  /**
     * 设置偏移
     */
   private void setPushToRegisterOffSet() {
            //水滴初始的位置
            float original = mStartPosition.y;
            float step = 0.6f;
            boolean isUp = (boolean) mPushRegisterLayout.getTag(R.string.isUp);
            float translationY;
            //根据水滴tag中的上下移动标识移动view
            if (isUp) {
                translationY = mPushRegisterLayout.getY() - step;
            } else {
                translationY = mPushRegisterLayout.getY() + step;
            }
            //对水滴位移范围的控制
            if (translationY - original > CHANGE_RANGE) {
                translationY = original + CHANGE_RANGE;
                mPushRegisterLayout.setTag(R.string.isUp, true);
            } else if (translationY - original < -CHANGE_RANGE) {
                translationY = original - CHANGE_RANGE;
                // FIXME:每次当水滴回到初始点时再一次设置水滴的速度,从而达到时而快时而慢
                mPushRegisterLayout.setTag(R.string.isUp, false);
            }
         mPushRegisterLayout.setY(translationY);
    }

因为安卓定义不能在子线程更改UI,所以我们使用安卓原生的Handler实现从子线程回到主线程来更UI界面,为什么要开启子线程去延时发送Handler处理的消息体呢?
因为根据android的OpenGl渲染界面需要1秒钟的时间,所以需要先让界面先渲染显示出来之后,再获取到控件的Y轴坐标值保存到一个Point里面,当然这个可以优化一下数据结构,节省内存的消耗。

 /**
     * 创建一个Handler,不断发送消息来更新下拉签到动画
     * @return
     */
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_PUSH_ANIMATION:
                    if(!isAnimation){//标识是否退出,防止界面销毁时,再一次改变UI
                        isAnimation = false;
                        return;
                    }
                    setPushToRegisterOffSet();
                    mHandler.sendEmptyMessageDelayed(START_PUSH_ANIMATION, DELAY_MILLIS);
                    break;
                default:
                    break;
            }
        }
    };```

最后也是比较容易忘记的一步就是在界面不可见的时候,要移除消息回调,不再后台发送消息更改控件位移位置。

mHandler.removeCallbacksAndMessages(this); //对用户不可见的时候,移除消息
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值