zoukankan      html  css  js  c++  java
  • android 开发进阶 自定义控件-仿ios自动清除控件

    先上图:



    开发中经常需要自定义view控件或者组合控件,某些控件可能需要一些额外的配置。比如自定义一个标题栏,你可能需要根据不同尺寸的手机定制不同长度的标题栏,或者更常见的你需要配置标题栏的背景,这时候,你就会考虑到你写的view的扩展性问题,通常情况下,我们可以为这个自定义的标题栏加上一些setXXX方法,供外界调用,设置其颜色、长度等属性。但是我们都知道,在使用系统控件时,我们大多数情况下并不需要在代码中配置控件,而仅仅只需在布局文件中对控件宽、高、颜色等进行配置,这样做的好处就将UI与业务逻辑解耦,使代码更加清晰

    自定义带属性的view控件在实现上非常简单,下面介绍步骤:

    1.编写attrs属性文件。android在默认情况下并没有attrs.xml,我们需要手动在values目录下新建一个这样的文件。文件根结点是resources,子节点叫declare-styleable,比如下面就是一个attrs文件:
    <?xml version="1.0" encoding="utf-8"?>    
    <resources>    
        <declare-styleable name="ClearEditTextView">    
            <attr name="icon_width" format="integer" />    
            <attr name="icon_height" format="integer" />    
        </declare-styleable>    
    </resources> 

    此处用来设置,EditText 右边的 清除按钮大小 宽,高

    2.编写自定义view。
    这个想必大家都不陌生,我这里需要继承EditText;
    package com.example.clearbuttonedit;
    
    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.app.Activity;
    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.util.DisplayMetrics;
    import android.widget.EditText;
    /**
    * 继承的EditText.
    *  
    * 对于自定义的View有EditText的属性,可以直接在xml文件中使用就可以了
    * 如果含有自己独特的属性,那么就需要在构造函数中获取属性文件attrs.xml中自定义属性的名称
    * 并根据需要设定默认值,放在在xml文件中没有定义。
    * 如果使用自定义属性,那么在应用xml文件中需要加上新的schemas,
    * 比如这里是xmlns:my="http://schemas.android.com/apk/res/com.example.clearbuttonedit"
    * 其中xmlns后的“my”是自定义的属性的前缀,res后的是我们应用所在的包
    * */
    public class ClearEditText extends EditText implements  
    		TextWatcher {
    
    	private Drawable mClearIcon;
    	 
    	private int clearIconWidth;
    	private int clearIconHeight;
    	
    	public ClearEditText(Context context) {
    		this(context, null);
    
    	}
    
    	public ClearEditText(Context context, AttributeSet attrs) {
    		this(context, attrs, android.R.attr.editTextStyle);
    
    	}
    
    	public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    		 
        	mClearIcon = getCompoundDrawables()[2]; 
            if (mClearIcon == null) { 
            	mClearIcon =getResources().getDrawable(R.drawable.clear_btn);
            }
    		getConfig(context, attrs);  
    		init();
    
    	}
    
        /** 
         * 从xml中获取配置信息 
         */ 
        private void getConfig(Context context, AttributeSet attrs) {
    		// TODO Auto-generated method stub
            //TypedArray是一个数组容器用于存放属性值  
            TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ClearEditTextView);  
              
            clearIconWidth = ta.getInt(R.styleable.ClearEditTextView_icon_width, mClearIcon.getIntrinsicWidth());  
            clearIconHeight = ta.getColor(R.styleable.ClearEditTextView_icon_height, mClearIcon.getIntrinsicHeight());  
            //用完务必回收容器  
            ta.recycle();  
    	}
    
    	private void init() { 
            mClearIcon.setBounds(0, 0, clearIconWidth, 
            		clearIconHeight);
            //设置控件,top bottom left right 图片(类似android:drawableLeft)
    		setCompoundDrawables(null, null, mClearIcon, null);
            //先隐藏清除按钮
            setClearIconVisible(false); 
            //监听EditText 内容改变
            addTextChangedListener(this);
        } 
    
        protected void setClearIconVisible(boolean visible) { 
            Drawable right = visible ? mClearIcon : null;
            setCompoundDrawables(getCompoundDrawables()[0], 
                    getCompoundDrawables()[1], right, getCompoundDrawables()[3]); 
        } 
         
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    	       if (getCompoundDrawables()[2] != null) { 
    	            if (event.getAction() == MotionEvent.ACTION_UP) {
    	            	boolean touchable = event.getX() > (getWidth() 
    	                        - getPaddingRight() - clearIconWidth) 
    	                        && (event.getX() < ((getWidth() - getPaddingRight())));
    	                if (touchable) { 
    	                    this.setText(""); 
    	                } 
    	            } 
    	        } 
    		// TODO Auto-generated method stub
    		return super.onTouchEvent(event);
    	}
    
    	//如果editText 控件文字大于 0 显示清除按钮
    	@Override
    	public void onTextChanged(CharSequence s, int start, int count, int after) {
    		setClearIconVisible(s.length() > 0); 
    	}
    
    	@Override
    	public void beforeTextChanged(CharSequence s, int start, int count,
    			int after) {
    
    	}
    
    	@Override
    	public void afterTextChanged(Editable s) {
    		// TODO Auto-generated method stub
    
    	}
    }
    

    (1)这里面的逻辑非常简单,需要注意的是这个getConfig方法,这个方法内部通过context和AttributeSet构造了一个TypedArray对象,这是个数组容器,里面存放的就是自定义属性和对应的值。该对象向外界暴露了一系列get方法,用于获取不同类型的属性值。TypedArray用完之后务必回收
    (2)使用 TextWatcher 监听 EditText内容变化,如果有文字就让清除按钮显示,没有就不显示;
    3.编写布局文件,使用上面的自定义的控件。
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:clearIcon="http://schemas.android.com/apk/res/com.example.clearbuttonedit"  
        android:layout_width="match_parent"
        android:layout_height="match_parent"
     
        tools:context=".MainActivity" >
    
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30sp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="20dp"
            android:text="登 录" />
    
        <com.example.clearbuttonedit.ClearEditText
            android:id="@+id/username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:hint="请输入用户名"
            android:layout_marginTop="20dp"
            android:layout_below="@id/title"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            clearIcon:icon_width="30"
            clearIcon:icon_height="30"
            android:background="@drawable/login_edit_selector"
            android:layout_centerHorizontal="true"
            >
        </com.example.clearbuttonedit.ClearEditText>
        
            <com.example.clearbuttonedit.ClearEditText
            android:id="@+id/pwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:layout_marginTop="10dp"
            android:layout_below="@id/username"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:hint="请输入密码"
            android:background="@drawable/login_edit_selector"
            android:layout_centerHorizontal="true"
            >
        </com.example.clearbuttonedit.ClearEditText>
    
    </RelativeLayout>

    需要注意的是,要想使用自定义属性,必须先加上命名空间,否则android不认识这些自定义属性。命名控件一般规则是  xmlns:[attrs中declare-styleable的name] = "http://schemas.android.com/apk/res/包名",

    4.在activity中通过 setContentView 加载布局

    demo下载:
    http://download.csdn.net/detail/q610098308/9299081

  • 相关阅读:
    创建spring自定义注解进行自动装配
    springmvc接收到的json数据乱码
    hibernate自动创建表失败
    Symfony2学习笔记之HTTP Cache
    EF4+Repository+UnitOfWork 代码摘录
    Symfony2学习笔记之表单
    Symfony2 学习笔记之内部构件
    Symfony2学习笔记之数据校验
    Symfony2 学习笔记之插件格式
    Symfony2学习笔记之数据库操作
  • 原文地址:https://www.cnblogs.com/sharecenter/p/5621029.html
Copyright © 2011-2022 走看看