Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
来源:互联网 发布:js input type 编辑:程序博客网 时间:2024/06/05 15:00
引言
前一篇文章 Android进阶——自定义View之系统控件架构及自定义控件概述从宏观整体上总结了关于自定义View的相关知识点,也说过自定义View有三种方式,这篇文章就作为我们开发自定义View优先考虑的解决方案——继承系统现有控件扩展功能的第一篇实战,主要是实现类似IOS风格的EditText,可以设置抖动动画和自带删除小图标的UI效果。
一、自定义加强型EditText功能概述
这个所谓的加强型EditText,其实就是添加了两种效果:当输入时自动添加上删除按钮和当输入为空的时候点击按钮触发非空的抖动动画,其他的和普通的EdiText无异。
二、自定义加强型EditText设计思想
首先我们知道android中任何一个控件其本质都是一个类,也同样拥有一些属性,无论是以java动态构造还是xml静态构造,最终显示到Activity上都需要先生成他们的实例,而任何一个类需要生成实例都需要通过它对应的构造方法,所以在构造方法里有很多事可以做。接下来再一步步分析下。
1、绘制出删除按钮
我们知道EditText继承自TextView,而我们知道TextView本身就自带drawableLeft、drawableRight、drawableTop、drawableRight属性可以在TextView的左右上下绘制对应的drawable,如下TextView源码所示,我们可以通过这个方法获取对应的drawable
/** * Returns drawables for the left, top, right, and bottom borders. * * @attr ref android.R.styleable#TextView_drawableLeft * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableRight * @attr ref android.R.styleable#TextView_drawableBottom */ @NonNull public Drawable[] getCompoundDrawables() { final Drawables dr = mDrawables; if (dr != null) { return dr.mShowing.clone(); } else { return new Drawable[] { null, null, null, null }; } }
2、动态改变删除按钮的显示和隐藏
当文本框里不为空的时候则显示;文本框为空的时候和失去焦点时则自动隐藏,我们都知道android为我们提供了个接口可以监听输入的变化——TextWatcher,我们只需要去实现这个接口并设置监听即可
/** * When an object of a type is attached to an Editable, its methods will be called when the text is changed.、 * 每当文本改变的时候就会依次出发三个回调方法 */public interface TextWatcher extends NoCopySpan { /** * This method is called to notify you that, within , * the characters beginning at start * are about to be replaced by new text. */ public void beforeTextChanged(CharSequence s, int start, int count, int after); /** * This method is called to notify you that, within characters beginning at start have just replaced old text /** * This method is called to notify you that, somewhere within the text has been changed. */ public void afterTextChanged(Editable s);}
至于失去焦点的时候自动隐藏,View类封装了很多接口方法,其中onFocusChange可以监听焦点改变事件
/** * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置右边图标的显示与隐藏 */ @Override public void onFocusChange(View v, boolean hasFocus) { this.isFocuse = hasFocus; if (hasFocus) { setRightIconVisiable(getText().length() > 0); } else { setRightIconVisiable(false); } }
4、实现点击右边按钮清空文本
控件的触屏事件的起点均是由Touch开始的,所以在一定程度上来说可以通过重写onTouch方法来模拟点击事件
/** * 模拟点击事件当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和EditText的宽度 - 图标到控件右边的间距 * 之间就相当于点击了右边的Icon */ @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (getCompoundDrawables()[2] != null) { boolean isRightClick = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight()))); if (isRightClick) { this.setText(""); } } } return super.onTouchEvent(event); }
5、抖动动画效果
只需要给控件添加上TranslateAnimation来实现位移动画即可。
private Animation genDefaultAnimation() { animtion = new TranslateAnimation(0, 10, 0, 0); animtion.setInterpolator(new CycleInterpolator(counts)); animtion.setDuration(during); return animtion; }
三、实现加强型EditText
package com.crazymo.training.widget;import android.content.Context;import android.content.res.TypedArray;import android.graphics.drawable.Drawable;import android.text.Editable;import android.text.TextWatcher;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.View.OnFocusChangeListener;import android.view.animation.Animation;import android.view.animation.CycleInterpolator;import android.view.animation.TranslateAnimation;import android.widget.EditText;import com.crazymo.training.R;/** * Created by cmo on 2016/10/6. * 加强型EditText:作为普通输入框可以设置非空提示的晃动动画效果,自带删除的按钮 */public class EnhancedEditText extends EditText implements OnFocusChangeListener, TextWatcher { private Drawable mRightIco;//显示于右边的Icon private Animation animtion;//用于提示非空的晃动动画 private boolean isFocuse;//当前是否获得焦点 private int counts; private int during; private float rightSize; private OnRightDrawableChanged rightChangedListener; public EnhancedEditText(Context context) { this(context, null); } public EnhancedEditText(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.editTextStyle);//直接引用系统的EditText的Style } public EnhancedEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); //引用自定义属性 TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.enhancedEditText); during=typedArray.getInt(R.styleable.enhancedEditText_during,2000); counts=typedArray.getInt(R.styleable.enhancedEditText_counts,6); rightSize=typedArray.getFloat(R.styleable.enhancedEditText_rightSize,0.7f); init(); } /** * 初始化右边的Icon和设置监听器 */ private void init() { //如果没有设置drawableRight属性则会获取默认的值,设置了drawableRight则会显示设置的值 mRightIco = getCompoundDrawables()[2]; if (mRightIco == null) { mRightIco = getResources().getDrawable(R.drawable.clear_selector); } //重新设置左边的Icon为左边Icon的大小 if(getCompoundDrawables()[0]!=null) { mRightIco.setBounds(0, 0, (int) ((getCompoundDrawables()[0].getIntrinsicWidth()) * rightSize), (int) ((getCompoundDrawables()[0].getIntrinsicHeight()) * rightSize)); }else { //若没有设置LeftDrawable的图像则默认设置右边的图像大小为96*96 mRightIco.setBounds(0, 0, 96, 96); } setRightIconVisiable(false);//默认设置隐藏图标 setOnFocusChangeListener(this);//设置焦点改变的监听 addTextChangedListener(this);//设置输入框里面内容发生改变的监听 } /** * 模拟点击事件当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和 * EditText的宽度 - 图标到控件右边的间距之间就相当于点击了右边的Icon */ @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (getCompoundDrawables()[2] != null) { boolean isRightClick = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight()))); if (isRightClick) { this.setText(""); } } } return super.onTouchEvent(event); } /** * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置右边图标的显示与隐藏 */ @Override public void onFocusChange(View v, boolean hasFocus) { this.isFocuse = hasFocus; if (hasFocus) { setRightIconVisiable(getText().length() > 0); } else { setRightIconVisiable(false); } } /** *设置Drawable显示于文字之上 setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) *设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去 * @param visible */ protected void setRightIconVisiable(boolean visible) { Drawable right = visible ? mRightIco : null; if(rightChangedListener!=null) { if (visible) { rightChangedListener.onRightDisplay(); } else { rightChangedListener.onRightInvisible(); } } setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]); } /** * 当输入框里面内容发生变化的时候回调的方法 */ @Override public void onTextChanged(CharSequence s, int start, int count, int after) { if (isFocuse) { setRightIconVisiable(s.length() > 0);//如果没有输入字符串则会隐藏 } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } /** * 启动晃动动画 * @param animation 可定义自定义的动画效果,若不定义则使用默认的动画 */ public void setShakeAnimation(Animation animation) { if(animation==null) { this.startAnimation(genDefaultAnimation()); }else{ this.startAnimation(animation); } } /** * 设置默认的晃动动画 * @return animation */ private Animation genDefaultAnimation() { animtion = new TranslateAnimation(0, 10, 0, 0); animtion.setInterpolator(new CycleInterpolator(counts)); animtion.setDuration(during); return animtion; } public void setRightChangedListener(OnRightDrawableChanged listener){ rightChangedListener=listener; } public interface OnRightDrawableChanged{ void onRightDisplay(); void onRightInvisible(); }}
四、应用自定义加强型EditText
package com.crazymo.training;import android.app.Activity;import android.os.Bundle;import android.text.TextUtils;import android.text.method.HideReturnsTransformationMethod;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.Toast;import com.crazymo.training.widget.EnhancedEditText;public class MainActivity extends Activity implements EnhancedEditText.OnRightDrawableChanged { private final String TAG="EnhanceEditText"; private Button btn; private EnhancedEditText clearEditText; private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init(){ getViews(); setBtnClickListener(); //clearEditText.setRightIco(getDrawable(R.mipmap.ic_user)); clearEditText.setRightChangedListener(this); } private void getViews(){ btn= (Button) findViewById(R.id.test_btn); clearEditText= (EnhancedEditText) findViewById(R.id.cleat_edt_user); imageView= (ImageView) findViewById(R.id.show_pwd); } private void setBtnClickListener(){ btn.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(TextUtils.isEmpty(clearEditText.getText())){ //设置晃动 clearEditText.setShakeAnimation(null); //设置提示 Toast.makeText(MainActivity.this,"用户名不能为空",Toast.LENGTH_LONG).show(); return; }else{ //设置密码可见 clearEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); //clearEditText.setRightIco(getDrawable(R.mipmap.ic_user)); //clearEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); } } }); } @Override public void onRightDisplay() { imageView.setVisibility(View.VISIBLE); } @Override public void onRightInvisible() { imageView.setVisibility(View.GONE); }}
五、输入法软键盘悬浮于文本框的下方
再也不用去特意嵌套ScrollView来实现了,只需要设置EditText的属性即可
android:imeOptions="flagNoExtractUi"
- Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
- Android进阶——自定义View之扩展系统控件的另一种思路实现渐变文字动画的TextView
- Android进阶——自定义View之重写ViewGroup组合系统控件实现自定义ToolBar模板
- Android进阶——自定义View之组合系统控件实现水珠形状的ItemView
- 自定义View之自定义EditText带删除内容按钮控件
- Android进阶:实现android系统自带查看照片动画效果 类似Gallery手势滑动
- Android属性动画与自定义View——实现vivo x6更新系统的动画效果
- 自定义悬浮按钮效果实现,带移动效果
- Android实现带动画效果的自定义View
- android 自定义View于软键盘之上
- Android 自定义View动画效果进阶
- Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)
- Android进阶——自定义View之继承ViewGroup实现自己的ScrollView
- Android自定义控件10----继承View实现水波纹效果
- Android继承自View和ViewGroup,自定义控件
- Android进阶——自定义View之必学的系统控件架构及自定义控件概述
- Android进阶——自定义View之扩展系统Dialog
- 自定义带删除按钮的 Edittext 并伴随动画效果
- 计算机算法:数据压缩之前缀编码
- linux中编译软件时 configure --prefix的作用
- web项目开发 之 前端规范 --- HTML编码规范
- if语句-分段函数1
- Virtualbox中添加现有磁盘错误的解决方法
- Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
- 一元多项式相加与相乘(C++)
- 【面试题】腾讯面试题之生成格雷码
- 2016弱校联盟十一专场10.7(12点场)-M. Subimage Recognition
- TCP,UDP编程区别
- 砥砺锋芒铸神剑- 高性价比工业级核心板 FETMX6UL
- 智慧北京项目总结
- 正规方程组
- iOS 跳转AppStore的两种方法,应用内和直接跳转