View的 isFocusableInTouchMode() 默认是 false, 需调用 setFocusableInTouchMode(true) 才为true
要让 button 等 view 调用 requestFocus 方法起作用, 需要 isFocusableInTouchMode() 为true才行。
setFocusable(false) 会到导致 isFocusable() 和 isFocusableInTouchMode() 都为false,
要设为true只能分别调用 setFocusable(true) 和 setFocusableInTouchMode(true)
只能有一个View得到焦点,其他的View将失去焦点.
Selected
可以有多个View同时处于 Selected状态。
View 的 setSelected方法,会调用 dispatchSetSelected 向子View传递 select状态。
public void setSelected(boolean selected) { if (((mPrivateFlags & SELECTED) != 0) != selected) { mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0); if (!selected) resetPressedState(); invalidate(); refreshDrawableState(); dispatchSetSelected(selected); } }
ViewGroup 的 dispatchSetSelected 方法。
public void dispatchSetSelected(boolean selected) { final View[] children = mChildren; final int count = mChildrenCount; for (int i = 0; i < count; i++) { children[i].setSelected(selected); } }
Selector
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/black" android:state_selected="true"/> <item android:drawable="@drawable/white"/> </selector>
ViewGroup 有多个重载的 addView方法
在xml布局文件里面添加的子View,是通过下面这个重载方法加到ViewGroup中的。
public void addView(View child, ViewGroup.LayoutParams params);
利用上述机制,可以简单的实现一个类似 TabWidget 的 tab 切换容器,支持用 selector 改变 tabView 和 tabView 子 View 的背景.
import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; public class TabContainer extends LinearLayout { private int mCurrentTab = -1; public TabContainer(Context context, AttributeSet attrs) { super(context, attrs); } public void setCurrentTab(int index) { if (getChildCount() == 0) { return; } if (index >= 0 && index <= getChildCount() - 1) { getChildAt(index).performClick(); } } @Override public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { super.addView(child, index, params); child.setOnClickListener(mOnClickListener); child.setSelected(false); } private View.OnClickListener mOnClickListener = new OnClickListener() { @Override public void onClick(View v) { int index = indexOfChild(v); if (index != mCurrentTab) { if (mCurrentTab >= 0) { getChildAt(mCurrentTab).setSelected(false); } getChildAt(index).setSelected(true); mCurrentTab = index; if (mOnTabSelectChangeListener != null) { mOnTabSelectChangeListener.onTabSelectChanged(index, v); } } } }; private OnTabSelectChangeListener mOnTabSelectChangeListener; public void setOnTabSelectChangeListener(OnTabSelectChangeListener listener) { mOnTabSelectChangeListener = listener; } public interface OnTabSelectChangeListener { public void onTabSelectChanged(int index, View tab); } }