概述:最近项目中,UI妹子需要我实现以下效果: 中间的文字和搜索图标慢慢向左移动。
最后我实现的效果: 在以前的项目中也实现过类似的功能只是少了动画的效果也是用自定义控件实现的传送门,不过这次和上次实现的方式大不一样。至于哪里不一样,请接着往下看。源码地址:点我下载吧,老铁
一 分析
在以前的实现中,我们使用了继承控件的自定义view实现方式。具体实现步骤,请查看以前的博客,传送门。其实两次的效果很明显可以发现只有多了动画这一点区别。在EditText中我们是没有办法用动画控制文字的移动的,所以我们考虑用组合控件的自定义view实现方式让EditText整个移动,达到我们想要的效果。
二 思路
在考虑使用组合控件自定义View实现之后,很明显我们的布局中有一个EditText接受我们的点击和输入事件,一个ImageView接受点击清除EditText内容的。最开始 ImageView在最右边,EditText的宽度是wrap_content居中的, 然后使用动画让整个EditText向左移动,在移动的过程中让EditText的宽度慢慢变成match_parent。考虑上面的种种情况,最终决定使用约束布局ConstraintLayout的方式实现。至于对ConstraintLayout还不熟悉的小伙伴,请阅读以下两篇文章:ConstraintLayout基础,ConstraintLayout使用,ConstraintLayout动画。
三 实现
(1)布局实现
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/constraint_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_clear"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:padding="4dp"
android:src="@drawable/btn_search_clear"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/et"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="@null"
android:cursorVisible="false"
android:drawableLeft="@drawable/icon_search"
android:drawablePadding="5dp"
android:focusable="false"
android:hint="搜索商品\品牌"
android:paddingLeft="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@+id/iv_clear"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
如果你阅读了上面推荐的ConstraintLayout博客,相信很容易就能读懂上面的布局代码,这里就不再赘述。
(2)自定义属性
<resources>
<!-- 带动画效果的有清楚按钮的EditText-->
<declare-styleable name="ConstraintEditText">
<!--imageView的宽 -->
<attr name="cet_iv_width" format="dimension|reference" />
<!--imageView的高 -->
<attr name="cet_iv_height" format="dimension|reference" />
<!--imageView的图片 -->
<attr name="cet_iv_src" format="reference" />
<!--imageView的padding,通过这个属性和宽高可以设置图片显示大小以及点击区域的大小 -->
<attr name="cet_iv_padding" format="dimension|reference" />
<!--imageView的marginRight,通过这个属性可以这是图片距离父控件的右边距离 -->
<attr name="cet_iv_marginRight" format="dimension|reference" />
<!--EditText背景 没有背景的时候默认为@null-->
<attr name="cet_et_bg" format="reference" />
<!--EditText左边搜索图标-->
<attr name="cet_et_left_drawable" format="reference" />
<!--EditText左边搜索图标距离文字位置-->
<attr name="cet_et_drawablePadding" format="reference" />
<!--EditText距离imageView距离-->
<attr name="cet_et_marginRight" format="dimension|reference" />
<!--EditText距离父控件左边距离-->
<attr name="cet_et_marginLeft" format="dimension|reference" />
<!--EditText是否显示光标-->
<attr name="cet_et_cursorVisible" format="boolean" />
<!--EditText初始是否获取焦点-->
<attr name="cet_et_focusable" format="boolean" />
<!--EditText图片左边距离本身控件左边的距离-->
<attr name="cet_et_paddingLeft" format="dimension|reference" />
<!--EditText提示文字-->
<attr name="cet_et_hint_text" format="string|reference" />
<!--EditText提示文字大小-->
<attr name="cet_et_hint_text_size" format="dimension|reference" />
<!--EditText提示文字颜色-->
<attr name="cet_et_text_hint_color" format="color|reference" />
<!--EditText输入文字-->
<attr name="cet_et_text" format="string|reference" />
<!--EditText输入文字大小-->
<attr name="cet_et_text_size" format="dimension|reference" />
<!--EditText输入文字颜色-->
<attr name="cet_et_text_color" format="color|reference" />
</declare-styleable>
</resources>
为了考虑效果和美观以及多种情况,属性有点多,注释很详细,不再解释。
(3)获取自定义属性
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
ConstraintLayout.inflate(context, R.layout.layout_contraint_clear_edit_text, this);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ConstraintEditText, defStyleAttr, 0);
// imageView
cet_iv_width = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_iv_width, 0);
cet_iv_height = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_iv_height, 0);
cet_iv_src = array.getDrawable(R.styleable.ConstraintEditText_cet_iv_src);
cet_iv_padding = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_iv_padding, 0);
cet_iv_marginRight = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_iv_marginRight, 0);
//EditText
cet_et_bg = array.getDrawable(R.styleable.ConstraintEditText_cet_et_bg);
cet_et_left_drawable = array.getDrawable(R.styleable.ConstraintEditText_cet_et_left_drawable);
cet_et_cursorVisible = array.getBoolean(R.styleable.ConstraintEditText_cet_et_cursorVisible, false);
cet_et_focusable = array.getBoolean(R.styleable.ConstraintEditText_cet_et_focusable, false);
cet_et_marginLeft = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_et_marginLeft, 0);
cet_et_marginRight = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_et_marginRight, 0);
cet_et_drawablePadding = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_et_drawablePadding, 0);
cet_et_paddingLeft = array.getDimensionPixelSize(R.styleable.ConstraintEditText_cet_et_paddingLeft, 0);
cet_et_hint_text = array.getString(R.styleable.ConstraintEditText_cet_et_hint_text);
cet_et_text = array.getString(R.styleable.ConstraintEditText_cet_et_text);
cet_et_hint_text_size = array.getDimension(R.styleable.ConstraintEditText_cet_et_hint_text_size, 16);
cet_et_text_size = array.getDimension(R.styleable.ConstraintEditText_cet_et_text_size, 18);
cet_et_text_hint_color = array.getColor(R.styleable.ConstraintEditText_cet_et_text_hint_color, Color.BLACK);
cet_et_text_color = array.getColor(R.styleable.ConstraintEditText_cet_et_text_color, Color.BLACK);
array.recycle();
}
api都很基础不再赘述。
(4)初始化控件
@Override
protected void onFinishInflate() {
super.onFinishInflate();
constraintLayout = findViewById(R.id.constraint_layout);
ivClear = findViewById(R.id.iv_clear);
et = findViewById(R.id.et);
setImageViewValue();
setEditTextValue();
mConstraintSet = new ConstraintSet();
mConstraintSet.clone(constraintLayout);
initListener();
}
//初始imageview的值
private void setImageViewValue() {
ivClear.getLayoutParams().width = cet_iv_width;
ivClear.getLayoutParams().height = cet_iv_height;
ivClear.setImageDrawable(cet_iv_src);
ivClear.setPadding(cet_iv_padding, cet_iv_padding, cet_iv_padding, cet_iv_padding);
setMargins(ivClear, 0, 0, cet_iv_marginRight, 0);
}
// 初始化EditTex的值
private void setEditTextValue() {
et.setBackgroundDrawable(cet_et_bg);
if (cet_et_left_drawable != null) {
cet_et_left_drawable.setBounds(0, 0, cet_et_left_drawable.getMinimumWidth(), cet_et_left_drawable.getMinimumHeight());
et.setCompoundDrawables(cet_et_left_drawable, null, null, null);
}
et.setCompoundDrawablePadding(cet_et_drawablePadding);
setMargins(et, cet_et_marginLeft, 0, cet_et_marginRight, 0);
et.setPadding(cet_et_paddingLeft, 0, 0, 0);
et.setCursorVisible(cet_et_cursorVisible);
et.setFocusable(cet_et_focusable);
et.setText(cet_et_text);
et.setHintTextColor(cet_et_text_hint_color);
et.setTextColor(cet_et_text_color);
et.setTextSize(TypedValue.COMPLEX_UNIT_PX, cet_et_text_size);
SpannableString ss = new SpannableString(cet_et_hint_text);//定义hint的值
AbsoluteSizeSpan ass = new AbsoluteSizeSpan((int) cet_et_hint_text_size, true);//设置字体大小 true表示单位是sp
ss.setSpan(ass, 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
et.setHint(new SpannedString(ss));
}
// 设置监听
private void initListener() {
//默认设置隐藏图标
setClearIconVisible(false);
//清除按钮监听
ivClear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
et.setText("");
}
});
// 设置EditText点击之后的动画 以及焦点设置
et.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (!flag) {
//动画
showAnimal();
et.setEnabled(true);
et.setFocusable(true);//可以通过键盘得到焦点
et.setFocusableInTouchMode(true);//可以通过触摸得到焦点
ivClear.setVisibility(GONE);
flag = true;
}
}
});
//设置输入框里面内容发生改变的监听
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (mHasFocus) {
setClearIconVisible(charSequence.length() > 0);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
// 焦点变化监听
et.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
mHasFocus = hasFocus;
if (hasFocus) {
setClearIconVisible(et.getText().length() > 0);
} else {
setClearIconVisible(false);
}
}
});
}
(5)动画
private void showAnimal() {
TransitionManager.beginDelayedTransition(constraintLayout);
mConstraintSet.clear(R.id.et);
mConstraintSet.connect(R.id.et, ConstraintSet.LEFT, R.id.constraint_layout, ConstraintSet.LEFT, 1000);
mConstraintSet.connect(R.id.et, ConstraintSet.RIGHT, R.id.iv_clear, ConstraintSet.LEFT);
mConstraintSet.connect(R.id.et, ConstraintSet.TOP, R.id.constraint_layout, ConstraintSet.TOP);
mConstraintSet.connect(R.id.et, ConstraintSet.BOTTOM, R.id.constraint_layout, ConstraintSet.BOTTOM);
mConstraintSet.applyTo(constraintLayout);
}
只要是看了上面推荐的ConstraintLayout动画介绍这点效果简直是easy啊。
四 源码
下载地址,点我吧,老铁