自定义控件

一、背景:

项目中要用到好多一模一样的控件,且每一个控件有自己的各种状态和相对独立的业务逻辑,为了使代码简洁、可复用可移植,把这个控件独立抽取出来,做成了一个自定义的控件。

二、自定义属性

实现一个自定义的控件,避免不了使用自己自定义的属性,自定义属性一般是在value文件夹中的attr.xml中建立自己自定义的标签。

    <!--自定义指纹图标的属性-->
    <declare-styleable name="FingerImage">
        <attr name="android:text"/>  <!--显示的文字,这里没有写format,意思是引用系统的属性,但是又不能不写,因为当前控件可能没有这个属性-->
        <attr name="android:textSize"/>  <!--文字大小,这里没有写format,意思是引用系统的属性,但是又不能不写,因为当前控件可能没有这个属性-->
        <attr name="img_bg" format="reference" />  <!--背景图-->
        <attr name="seleted" format="boolean" />   <!--是否被选中-->
        <attr name="finger_index">  <!--枚举类型不用指定format,且value必须为int类型-->
            <enum name="left_1" value="1" />
            <enum name="left_2" value="2" />
            <enum name="left_3" value="3" />
            <enum name="left_4" value="4" />
            <enum name="left_5" value="5" />
            <enum name="right_1" value="6" />
            <enum name="right_2" value="7" />
            <enum name="right_3" value="8" />
            <enum name="right_4" value="9" />
            <enum name="right_5" value="10" />
        </attr>
    </declare-styleable>

三、在布局文件中使用自定义属性

首先在根布局声明命名空间 : xmlns:myApp=”http://schemas.android.com/apk/res-auto”

    <com.hisign.id_verification.viewsupport.FingerImage
        android:id="@+id/img_l1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="拇指"
        android:textSize="@dimen/img_fp_txt_size"
        myApp:img_bg="@drawable/img_finger_selector"
        myApp:finger_index="left_1"
        myApp:seleted="true"/>

四、自定义控件的布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="true"
    android:orientation="vertical"
    android:gravity="center">
    <ImageView
        android:id="@+id/img_finger"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        *style="@style/img_finger"* />
    <TextView
        android:id="@+id/tv_finger"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:textColor="@color/white_alpha_percentage50"
        android:textSize="18sp"/>
</LinearLayout>

这里面还用到了自定义的样式(其实就是把多个原生的属性放在了一起,减少了代码量,看起来更简洁更好修改)
在value文件夹的style.xml中建立一个新的标签

    <style name="img_finger">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginLeft">@dimen/img_fp_margin</item>
        <item name="android:layout_marginTop">@dimen/img_fp_margin</item>
        <item name="android:layout_marginRight">@dimen/img_fp_margin</item>
        <item name="android:layout_marginBottom">@dimen/img_fp_margin_bottom</item>
        <item name="android:background">@drawable/img_finger_selector</item>
        <item name="android:scaleType">fitXY</item>
    </style>

使用时:style=”@style/img_finger”

五、自定义控件类中自定义属性的获得

TypedArray ta = mContext.obtainStyledAttributes(attrs, R.styleable.FingerImage);
    String txt = ta.getString(R.styleable.FingerImage_android_text);
    int bgResId = ta.getResourceId(R.styleable.FingerImage_img_bg,R.drawable.img_finger_selector);
    int mTextSize = ta.getDimensionPixelSize(R.styleable.FingerImage_android_textSize, 18);
    boolean isSelected = ta.getBoolean(R.styleable.FingerImage_seleted,false);
    hasFocus = isSelected;
    String fingerIndex = ta.getString(R.styleable.FingerImage_finger_index);

六、全部代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.hisign.id_verification.R;
import com.hisign.id_verification.app.MyApplication;
import com.hisign.id_verification.manager.CapFingerManager;
import com.hisign.id_verification.manager.Const;
import com.hisign.id_verification.manager.EventObject;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by lixm on 2017/12/11.
 */
public class  FingerImage extends LinearLayout implements View.OnClickListener,View.OnFocusChangeListener{

    @BindView(R.id.img_finger)
    ImageView imgFinger;

    @BindView(R.id.tv_finger)
    TextView  tvFinger;

    private Context mContext;

    private OnClickListener listener;

    /**
     * 当前指位的名称
     */
    private String curFingerIndexName;

    /**
     * 当前指位的第一枚指纹
     */
    private Bitmap fpBmp1;

    /**
     * 当前指位的第二枚指纹
     */
    private Bitmap fpBmp2;

    /**
     * 当前指位的采集状态
     */
    private FingerState curState;

    private String[] fingerIndexNames = {"左手拇指","左手食指","左手中指","左手无名指","左手小指",
                                            "右手拇指","右手食指","右手中指","右手无名指","右手小指"};

    /**
     * 采集完当前两枚指纹后的回调
     */
    private OnCapComeleptedListener onCapComeleptedListener;

    private boolean hasFocus = false;

    public FingerImage(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        View view = LayoutInflater.from(context).inflate(R.layout.layout_icon_finger_item, this, true);
        ButterKnife.bind(view);
        Log.d("lixm","FingerImage(2)... ");
        initAttributes(attrs);
    }

    public FingerImage(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        Log.d("lixm","FingerImage(3)... ");
        View view = LayoutInflater.from(context).inflate(R.layout.layout_icon_finger_item, this, true);
        ButterKnife.bind(view);
        initAttributes(attrs);
    }

    /**
     * 解析属性信息
     * @param attrs
     */
    private void initAttributes(AttributeSet attrs){
        // 设置点击事件
        imgFinger.setOnClickListener(this);
        // 设置焦点变化事件
        imgFinger.setOnFocusChangeListener(this);

        TypedArray ta = mContext.obtainStyledAttributes(attrs, R.styleable.FingerImage);
        String txt = ta.getString(R.styleable.FingerImage_android_text);
        int bgResId = ta.getResourceId(R.styleable.FingerImage_img_bg,R.drawable.img_finger_selector);
        int mTextSize = ta.getDimensionPixelSize(R.styleable.FingerImage_android_textSize, 18);
        boolean isSelected = ta.getBoolean(R.styleable.FingerImage_seleted,false);
        hasFocus = isSelected;
        String fingerIndex = ta.getString(R.styleable.FingerImage_finger_index);
        curFingerIndexName = fingerIndexNames[Integer.parseInt(fingerIndex) - 1];
        Log.d("lixm","txt = " + txt + ", mTextSize = " + mTextSize + ", curFingerIndexName = " + curFingerIndexName + ", isSelected = " + isSelected);
        imgFinger.setBackgroundResource(bgResId);
        tvFinger.setText(txt);
        tvFinger.setTextSize(mTextSize);
        if(isSelected){
            setState(FingerState.SELECTED);
        }else{
            setState(FingerState.NORMAL);
        }
    }

    /**
     * 设置指纹图片的背景
     * @param bgRes
     */
    public void setBg(int bgRes){
        imgFinger.setBackgroundResource(bgRes);
    }

    /**
     * 设置指纹的文字信息
     * @param txt
     */
    public void setTxt(String txt){
        tvFinger.setText(txt);
    }

    /**
     * 设置文字的大小
     * @param txtSize
     */
    public void setTxtSize(int txtSize){
        tvFinger.setTextSize(txtSize);
    }

    /**
     * 指纹采集当前的状态
     * @param state
     */
    public void setState(FingerState state){
        curState = state;
        if(state == FingerState.SELECTED){
            imgFinger.setBackgroundResource(R.drawable.img_fp_p);
            tvFinger.setTextColor(mContext.getResources().getColor(R.color.white));
        }else if(state == FingerState.CAP_ONE){
            imgFinger.setBackgroundResource(R.drawable.img_fp_one);
            tvFinger.setTextColor(mContext.getResources().getColor(R.color.white));
        }else if(state == FingerState.CAP_TWO){
            imgFinger.setBackgroundResource(R.drawable.img_fp_two);
            tvFinger.setTextColor(mContext.getResources().getColor(R.color.white));
        }else if(state == FingerState.NORMAL){
            imgFinger.setBackgroundResource(R.drawable.img_fp_n);
            tvFinger.setTextColor(mContext.getResources().getColor(R.color.white_alpha_percentage50));
        }else{
            imgFinger.setBackgroundResource(R.drawable.img_fp_n);
            tvFinger.setTextColor(mContext.getResources().getColor(R.color.white_alpha_percentage50));
        }
    }

    @Override
    public void onClick(View v) {
        Log.d("lixm","onClick...");
        CapFingerManager.getInstance().startCapFpbmp();
        imgFinger.requestFocus();
        this.setState(FingerState.SELECTED);
    }

    public void setOnClickListener(OnClickListener listener){
        this.listener = listener;
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        this.hasFocus = hasFocus;
        if(hasFocus){
            this.setState(FingerState.SELECTED);
            EventBus.getDefault().register(this);
        }else{
            EventBus.getDefault().unregister(this);
            if(curState != FingerState.CAP_TWO){   // 如果已经采集完成,在失去焦点时依然保持采集完成的状态
                this.setState(FingerState.NORMAL);
                fpBmp1 = null;
                fpBmp2 = null;
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void showEventBusMsg(EventObject obj) {
        String action = obj.eventAction;
        if(Const.EVENT_ACTION.CAP_FINGER_INFO.equals(action)) {
            int type = obj.eventType;
            if (type == Const.EVENT_TYPE.TYPE_SUCCEED) {
                Bitmap bmp = (Bitmap) obj.eventData;
                if(curState == FingerState.SELECTED){
                    fpBmp1 = bmp;
                    setState(FingerState.CAP_ONE);
                    MyApplication.getMyApplication().mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            if(hasFocus){
                                CapFingerManager.getInstance().startCapFpbmp();
                            }
                        }
                    },2000);
                }else if(curState == FingerState.CAP_ONE){
                    fpBmp2 = bmp;
                    setState(FingerState.CAP_TWO);
                    if(onCapComeleptedListener != null){
                        onCapComeleptedListener.onCapFingerFinish(curFingerIndexName,fpBmp1,fpBmp2);
                    }
                    CapFingerManager.getInstance().stopCapFpbmp();
                }
            }
        }else if(Const.EVENT_ACTION.CAP_FINGER_INFO_TIME_OUT.equals(action)){

        }
    }

    /**
     * 返回当前指位的名称
     * @return
     */
    public String getFingerName(){
        return curFingerIndexName;
    }

    public void setOnCapComeleptedListener(OnCapComeleptedListener onCapComeleptedListener) {
        this.onCapComeleptedListener = onCapComeleptedListener;
    }

   public interface OnCapComeleptedListener {
       void onCapFingerFinish(String curFingerIndexName,Bitmap bmp1,Bitmap bmp2);
    }

    /**
     * 指纹采集当前的状态
     */
    public enum FingerState{
        NORMAL,
        SELECTED,
        CAP_ONE,
        CAP_TWO
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值