1. 程式人生 > >子控制元件搶佔父控制元件事件響應

子控制元件搶佔父控制元件事件響應

1.在普通佈局中,父控制元件中含有button、ImageButton、CheckBox、EditText,RatingBar等時,點選事件失效。

例如:列表中的item佈局中含有RatingBar子控制元件。

在item的根佈局檔案中加入:android:descendantFocusability=”blocksDescendants”

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width
="match_parent" android:layout_height="48dp" android:descendantFocusability="blocksDescendants">
<TextView android:id="@+id/tv_store_listitem_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="哈爾濱神燈汽修"/> <RatingBar
android:id="@+id/rb_store_listitem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:max="5" android:progress="2" android:stepSize="1"/>
</LinearLayout>

descendantFocusability屬性

android
:descendantFocusability

該屬性是當一個為view獲取焦點時,定義viewGroup和其子控制元件兩者之間的關係。
屬性的值有三種:
beforeDescendants:viewgroup會優先其子類控制元件而獲取到焦點
afterDescendants:viewgroup只有當其子類控制元件不需要獲取焦點時才獲取焦點
blocksDescendants:viewgroup會覆蓋子類控制元件而直接獲得焦點

2.自定義組合控制元件中含有button、ImageButton、CheckBox、EditText,RatingBar等時,使自定義的組合控制元件點選事件失效。而響應子view的事件

在自定義view中重寫onInterceptTouchEvent()方法,它會在事件傳給孩子之前被呼叫。從而實現事件分配不到給子View時就將事件攔截下來。

例如自定義FrameLayout佈局,佈局中含有一個TextView和一個EditText。通過判斷自定義屬性isContentFocus來判斷是否響EditText的事件。如果傳過來的值是true,那麼就相應EditText事件不響應自定義佈局事件,如果傳過來的值是false,那麼取消EditText事件響應實現自定義佈局的事件響應。

自定義SettingItemView組合控制元件繼承FrameLayout

public class SettingItemView extends FrameLayout{
    private static final String TAG = "ZCN=SettingItemView";
    private EditText etMsg;
    private TextView tvTitle;

    private static final int DEFAULT_TEXT_COLOR = Color.BLACK;
    private static final int DEFAULT_EDIT_COLOR = Color.TRANSPARENT;
    private String titleText;
    private float titleSize;
    private int titleColor;
    private boolean isTitleHide;
    private float contentSize;
    private int contentColor;
    private int contentHintColor;
    private String contentText;
    private boolean isContentFocus;
    private int contentLength;
    private int inputType;

    private int DEFAULT_TITLE_SIZE = 16;
    private int DEFAULT_TITLE_COLOR = Color.GRAY;
    private boolean DEFAULT_TITLE_HIDE = false;
    private int DEFAULT_CONTENT_SIZE = 16;
    private int DEFAULT_CONTENT_COLOR = Color.BLACK;
    private int DEFAULT_CONTENT_HINT_COLOR = Color.GRAY;
    private boolean DEFAULT_CONTENT_FOCUS = true;
    private int DEFAULT_CONTENT_LENGTH = 20;

    public SettingItemView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initAttrs(context, attrs);

        initView(context);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        Log.d(TAG,"=====initAttrs=====");
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.SettingItemView);
        titleText = typedArray.getString(R.styleable.SettingItemView_title_text);
        titleSize =  typedArray.getDimension(R.styleable.SettingItemView_title_size, DEFAULT_TITLE_SIZE);
        titleColor = typedArray.getColor(R.styleable.SettingItemView_title_color, DEFAULT_TITLE_COLOR);
        isTitleHide = typedArray.getBoolean(R.styleable.SettingItemView_title_hide, DEFAULT_TITLE_HIDE);
        contentText = typedArray.getString(R.styleable.SettingItemView_content_text);
        contentSize =  typedArray.getDimension(R.styleable.SettingItemView_content_size, DEFAULT_CONTENT_SIZE);
        contentColor = typedArray.getColor(R.styleable.SettingItemView_content_color, DEFAULT_CONTENT_COLOR);
        contentHintColor = typedArray.getColor(R.styleable.SettingItemView_content_hint_color, DEFAULT_CONTENT_HINT_COLOR);
        isContentFocus = typedArray.getBoolean(R.styleable.SettingItemView_content_focus, DEFAULT_CONTENT_FOCUS);
        contentLength = typedArray.getInteger(R.styleable.SettingItemView_content_length,DEFAULT_CONTENT_LENGTH);
        inputType = typedArray.getInteger(R.styleable.SettingItemView_content_input_type,1);
        typedArray.recycle();
    }

    private void initView(Context context) {
        Log.d(TAG,"=====initView=====");
        LayoutInflater.from(context).inflate(R.layout.view_setting_item, this);// 載入佈局
        etMsg = (EditText) findViewById(R.id.et_setting_item);// 獲取控制元件
        tvTitle = (TextView) findViewById(R.id.tv_setting_item);

        tvTitle.setText(titleText);
        tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,titleSize);
        //如果不設定這個文字會變得非常大
        tvTitle.getPaint().setTextSize(titleSize);
        tvTitle.setTextColor(titleColor);
        if(isTitleHide){
            tvTitle.setVisibility(GONE);
        }

        etMsg.setText(contentText);
        etMsg.setTextSize(TypedValue.COMPLEX_UNIT_SP,contentSize);
        //如果不設定這個文字會變得非常大
        etMsg.getPaint().setTextSize(contentSize);
        etMsg.setTextColor(contentColor);
        etMsg.setHintTextColor(contentHintColor);
        etMsg.setFilters(new InputFilter[]{new InputFilter.LengthFilter(contentLength)});
        etMsg.setInputType(inputType);
        if(!isContentFocus){
            etMsg.setFocusable(false);
            etMsg.setClickable(false);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d(TAG,"=====onInterceptTouchEvent=====");

        //如果editText傳過來放棄焦點的值,那麼layout擷取事件並響應事件
        return !isContentFocus;
    }

    //設定EditText值
    public void setContentText(String str){
        etMsg.setText(str);
    }

    //獲取EditText值
    public String getContentText(){
        return etMsg.getText().toString().trim();
    }

}

attrs.xml檔案

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SettingItemView">
        <attr name="title_text" format="string"/>
        <attr name="title_color" format="color"/>
        <attr name="title_size" format="dimension"/>
        <attr name="title_hide" format="boolean"/>
        <attr name="content_text" format="string"/>
        <attr name="content_size" format="dimension"/>
        <attr name="content_color" format="color"/>
        <attr name="content_length" format="integer"/>
        <attr name="content_input_type" format="integer"/>
        <attr name="content_hint_color" format="color"/>
        <attr name="content_focus" format="boolean"/>
    </declare-styleable>
</resources>

view_setting_item.xml佈局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:id="@+id/et_setting_item"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@android:color/transparent"
        android:singleLine="true"
        android:gravity="center"/>
    <TextView
        android:id="@+id/tv_setting_item"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:gravity="center_vertical"
        android:layout_marginLeft="16dp"/>

</FrameLayout>

在佈局中使用自定義View

<!--//將content_focus屬性值置為ture,就會響應EditText事件,置為false會響應SettingItemView的點選事件-->
<com.sdlj.vehiclerepair.view.SettingItemView
     android:id="@+id/siv_setting_name"
     style="@style/setting_setting_item_view"
     android:layout_marginBottom="@dimen/setting_gap_view_height"
     android:layout_marginTop="@dimen/setting_gap_view_height"
     app:title_text="@string/setting_name"
     app:content_focus="false"
/>