您的位置:首页 > 移动开发 > Android开发

Android自定义View示例(一)—带有删除按钮的EditText

2015-09-21 15:52 751 查看
首先,看一下效果图



MainActivity如下:

/**
 * Demo描述:
 * 自定义控件实现带清除功能的EditText
 * 
 * 学习资料:
 * http://blog.csdn.net/xiaanming/article/details/11066685  * 
 * Thank you very much
 */
public class MainActivity extends Activity {
    private CleanableEditText mUserNameCleanableEditText;
    private CleanableEditText mPassWordCleanableEditText;
    private Button mLoginButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
    }

    private void init(){
        mUserNameCleanableEditText=(CleanableEditText) findViewById(R.id.userNameEditText);
        mPassWordCleanableEditText=(CleanableEditText) findViewById(R.id.passwordEditText);
        mLoginButton=(Button) findViewById(R.id.loginButton);
        mLoginButton.setOnClickListener(new OnClickListenerImpl());
    }

    private class OnClickListenerImpl implements OnClickListener {
        @Override
        public void onClick(View view) {
            if (TextUtils.isEmpty(mUserNameCleanableEditText.getText())) {
                mUserNameCleanableEditText.setShakeAnimation();
                Toast.makeText(MainActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
            }

            if (TextUtils.isEmpty(mPassWordCleanableEditText.getText())) {
                mPassWordCleanableEditText.setShakeAnimation();
                Toast.makeText(MainActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();
            }
        }

    }

}


CleanableEditText如下:

/**
 * 在焦点变化时和输入内容发生变化时均要判断是否显示右边clean图标
 */
public class CleanableEditText extends EditText {
    private Drawable mRightDrawable;
    private boolean isHasFocus;

    public CleanableEditText(Context context) {
        super(context);
        init();
    }
    public CleanableEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CleanableEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
        //getCompoundDrawables:
        //Returns drawables for the left, top, right, and bottom borders.
        Drawable [] drawables=this.getCompoundDrawables();

        //取得right位置的Drawable
        //即我们在布局文件中设置的android:drawableRight
        mRightDrawable=drawables[2];    

        //设置焦点变化的监听
        this.setOnFocusChangeListener(new FocusChangeListenerImpl());
        //设置EditText文字变化的监听
        this.addTextChangedListener(new TextWatcherImpl());
        //初始化时让右边clean图标不可见
        setClearDrawableVisible(false);
    }

    /**
     * 当手指抬起的位置在clean的图标的区域
     * 我们将此视为进行清除操作
     * getWidth():得到控件的宽度
     * event.getX():抬起时的坐标(改坐标是相对于控件本身而言的)
     * getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离
     * getPaddingRight():clean的图标右边缘至控件右边缘的距离
     * 于是:
     * getWidth() - getTotalPaddingRight()表示:
     * 控件左边到clean的图标左边缘的区域
     * getWidth() - getPaddingRight()表示:
     * 控件左边到clean的图标右边缘的区域
     * 所以这两者之间的区域刚好是clean的图标的区域
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_UP:

            boolean isClean =(event.getX() > (getWidth() - getTotalPaddingRight()))&&
                             (event.getX() < (getWidth() - getPaddingRight()));
            if (isClean) {
                setText("");
            }
            break;

        default:
            break;
        }
        return super.onTouchEvent(event);
    }

    private class FocusChangeListenerImpl implements OnFocusChangeListener{
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
             isHasFocus=hasFocus;
             if (isHasFocus) {
                 boolean isVisible=getText().toString().length()>=1;
                 setClearDrawableVisible(isVisible);
            } else {
                 setClearDrawableVisible(false);
            }
        }

    }

    //当输入结束后判断是否显示右边clean的图标
    private class TextWatcherImpl implements TextWatcher{
        @Override
        public void afterTextChanged(Editable s) {
             boolean isVisible=getText().toString().length()>=1;
             setClearDrawableVisible(isVisible);
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before,int count) {

        }

    }   

    //隐藏或者显示右边clean的图标
    protected void setClearDrawableVisible(boolean isVisible) {
        Drawable rightDrawable;
        if (isVisible) {
            rightDrawable = mRightDrawable;
        } else {
            rightDrawable = null;
        }
        //使用代码设置该控件left, top, right, and bottom处的图标
        setCompoundDrawables(getCompoundDrawables()[0],getCompoundDrawables()[1], 
                             rightDrawable,getCompoundDrawables()[3]);
    } 

    // 显示一个动画,以提示用户输入
    public void setShakeAnimation() {
        this.setAnimation(shakeAnimation(5));
    }

    //CycleTimes动画重复的次数
    public Animation shakeAnimation(int CycleTimes) {
        Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10);
        translateAnimation.setInterpolator(new CycleInterpolator(CycleTimes));
        translateAnimation.setDuration(1000);
        return translateAnimation;
    }

}


main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"
    >

    <cc.textview5.CleanableEditText
        android:id="@+id/userNameEditText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="username"
        android:layout_marginTop="30dip"
        android:drawableLeft="@drawable/icon_user"
        android:drawableRight="@drawable/clean_selector"
         />

     <cc.textview5.CleanableEditText
        android:id="@+id/passwordEditText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="password"
        android:password="true"
        android:layout_marginTop="100dip"
        android:drawableLeft="@drawable/account_icon"
        android:drawableRight="@drawable/clean_selector"
         />

     <Button
         android:id="@+id/loginButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Login"
        android:layout_marginTop="155dip"
         />

</RelativeLayout>


总结:

1.自定义控件,首先得注意构造函数的编写,如:

public ClearEditText(Context context, AttributeSet attrs) { 

        // 这里构造方法也很重要,不加这个很多属性不能再XML里面定义 

        this(context, attrs, android.R.attr.editTextStyle); 

    }


2.下面这几个方法比较容易混淆,要注意:

getWidth():得到控件的宽度 

     * event.getX():抬起时的坐标(改坐标是相对于控件本身而言的) 

     * getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离 

     * getPaddingRight():clean的图标右边缘至控件右边缘的距离
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: