1. 前言
最近在干一件大事,好像很久没写博客,周末虽然忙了两天但是没看书也没干啥,失败的周末。。。
上周五在群里看到一个需求,如下图。已经工作上已经闲了一周了,反正自己在做自己的事情,就试着写了下,没想到竟然做不出下面的需求。
很容易看出来 UI 想要的效果,无非点击对应控件,背景滑动。
2. 实现
分析下:
1. 点击黄色背景滑动,说明布局时应该要使用到 FrameLayout ,然后上下两层中 有一层要透明,因为黄色背景是必须的,所以需要将 上面一层 密码 验证码 背景设置成透明,不然他们的颜色会覆盖黄色。
2. 点击滑动,说明需要设置动画,这里是使用 补间动画 还是 属性动画呢,无所谓 不影响,因为这黄色背景的动画没实际意义,这里没关系,当然最好还是用 属性动画。
3. 黄色背景的宽度,这里是最难的。因为只要知道背景的宽度就可以知道 动画移动的距离,直接将布局总宽度减去背景的宽度就是移动距离。
仔细看下 UI 图,黄色背景宽度应该有两种方式确定,第一:不管怎样,占总宽度的一般,第二:文本 密码的左间距+文本的宽度+同样长度的右间距。如下图
最好的效果应该是第二种,计算同样的左右间距。但是这里就有问题了,一边三个字 一边两个字,这文本的长度不能定死,宽度也就不能定死了。
2.1 代码
首先上代码布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<View
android:id="@+id/view"
android:layout_gravity="right"
android:background="@drawable/bg_2"
android:layout_width="0dp"
android:layout_height="28dp" />
<RelativeLayout
android:id="@+id/rl"
android:background="@drawable/bg_1"
android:layout_width="88dp"
android:layout_height="28dp">
<TextView
android:id="@+id/tv1"
android:textColor="#333333"
android:layout_marginLeft="10dp"
android:textSize="12sp"
android:text="密码"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv2"
android:textColor="#333333"
android:layout_marginRight="10dp"
android:textSize="12sp"
android:text="验证码"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</FrameLayout>
现在计算黄色背景的宽度,可以看到上面布局黄色背景宽度我设置的是 0dp ,因为这个宽度需要计算,这里设置多少都无所谓。
这里使用 layoutparams 获取宽度,因为这里涉及到 文本控件tv 宽度的获取,所以不能在 activity 的生命周期中获取
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
setBGWidth();
}
/**
* 设置黄色背景的宽度
*/
private void setBGWidth(){
RelativeLayout.MarginLayoutParams marginLP = (RelativeLayout.MarginLayoutParams) tv1.getLayoutParams();
/**
* 获取到tv控件左间距
*/
int leftMargin = marginLP.leftMargin;
FrameLayout.LayoutParams bgLP = new FrameLayout.LayoutParams(bgView.getLayoutParams());
/**
* 黄色背景宽度 = 左间距 + tv宽度 + 右间距
*/
bgLP.width = leftMargin + tv1.getWidth() + leftMargin;
bgView.setLayoutParams(bgLP);
}
接下来动画比较简单,其中一个xml如下
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="0"
android:duration="1000"
android:fillAfter="true"
>
</translate>
启动动画
final Animation transToRight = AnimationUtils.loadAnimation(this, R.anim.toright);
final Animation transToLeft = AnimationUtils.loadAnimation(this, R.anim.toleft);
bgView.startAnimation(transToLeft);
用属性动画,获取到移动的距离
/**
* 获取移动偏移值
* @return
*/
private int getTransValue(){
int offValue = 0;
int allVaule = rl.getWidth();
int mVaule = bgView.getWidth();
offValue = allVaule-mVaule;
return offValue;
}
移动动画
private void toLeft(){
int v = getTransValue();
ObjectAnimator anitRight = ObjectAnimator.ofFloat(bgView, "translationX", v,0);
anitRight.setDuration(1000);
anitRight.start();
}
效果图和上面一样 就不贴了,发现没,有种蛋疼的感觉,好像达不到 UI 的要求。
恩 就刚才 我在写博客的时候,修改了下代码,每次开始移动动画前 修改 黄色背景view的宽度 ,说实话 不是很好看
![]()
效果不是很好,可能与 UI 设计的有关,毕竟滑动前有点点停顿,也可能与插值器有关,加个插值器应该好点,毕竟这个移动 “太均匀”了
3. 源码
如果帮到给个star支持下 thx
https://github.com/GuoZhaoHui628/VerifyAnim