焦点问题

button被继承后focuseable=false;必须到style中手动配置为true.


    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

    这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

 

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

        beforeDescendants:viewgroup会优先其子类控件而获取到焦点

        afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

        blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

 

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)
<item name="android:focusableInTouchMode">true</item>            <item name="android:focusableInTouchMode">true</item> 


  public boolean onKey(View v, int keyCode, KeyEvent event) {

        if (event.getAction() == KeyEvent.ACTION_DOWN) {             if (v == mMethodList) {                 if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN                         && mMethodList.getSelectedItemPosition() == mMethodList                                 .getCount() - 1) {                     return true;                 }             } else if (v == mLanguageList) {                 if (keyCode == KeyEvent.KEYCODE_DPAD_UP                         && mLanguageList.getSelectedItemPosition() == 0) {                     return true;                 }             }         }         return false;     }             final View v = getRootView().focusSearch(View.FOCUS_UP);             if (v instanceof Header) {                 return true;             } else {                 return v.requestFocus();             } Date:   Sat Feb 2 15:13:11 2013 +0800     Fix issue#3266,#3264: Modify the focus error. Add the focus state of TabWidget.          Change-Id: Ie6dcad38bccfeff19f40bb866295f135b69d5867 diff --git a/res/drawable/tab_item.xml b/res/drawable/tab_item.xml index 56f9f32..3b11e83 100644 --- a/res/drawable/tab_item.xml +++ b/res/drawable/tab_item.xml @@ -19,6 +19,6 @@        <item android:drawable="@drawable/tab_item_focused" android:state_pressed="true"/>      <item android:drawable="@drawable/tab_item_focused" android:state_focused="true"/> -    <item android:drawable="@drawable/tab_item_focused" android:state_selected="true"/> +    <item android:drawable="@drawable/tab_item_selected" android:state_selected="true"/>    </selector> \ No newline at end of file diff --git a/res/drawable/tab_item_focused.9.png b/res/drawable/tab_item_focused.9.png index 7d65883..7867847 100644 Binary files a/res/drawable/tab_item_focused.9.png and b/res/drawable/tab_item_focused.9.png differ diff --git a/res/drawable/tab_item_selected.9.png b/res/drawable/tab_item_selected.9.png new file mode 100644 index 0000000..7d65883 Binary files /dev/null and b/res/drawable/tab_item_selected.9.png differ diff --git a/res/layout/net_wifi_hotspot.xml b/res/layout/net_wifi_hotspot.xml index 541b3f1..1f69259 100644 --- a/res/layout/net_wifi_hotspot.xml +++ b/res/layout/net_wifi_hotspot.xml @@ -71,7 +71,7 @@          android:layout_width="match_parent"          android:layout_height="wrap_content" >   -        <Button +        <com.togic.settings.view.ButtonItem              android:id="@+id/hotspot_save_btn"              style="@style/Button"              android:layout_alignParentRight="true" diff --git a/res/layout/net_wire_ip_setting.xml b/res/layout/net_wire_ip_setting.xml index 22ea749..a345226 100755 --- a/res/layout/net_wire_ip_setting.xml +++ b/res/layout/net_wire_ip_setting.xml @@ -52,7 +52,7 @@          style="@style/ListItem"          togic:title="@string/second_dns" />   -    <Button +    <com.togic.settings.view.ButtonItem          android:id="@+id/ip_save_btn"          android:layout_gravity="right"          android:text="@string/save" diff --git a/res/layout/net_wireless_ip_setting.xml b/res/layout/net_wireless_ip_setting.xml index 05a8377..ac4e287 100755 --- a/res/layout/net_wireless_ip_setting.xml +++ b/res/layout/net_wireless_ip_setting.xml @@ -62,7 +62,7 @@          style="@style/ListItem"          togic:title="@string/second_dns" />   -    <Button +    <com.togic.settings.view.ButtonItem          android:id="@+id/ip_save_btn"          android:layout_gravity="right"          android:gravity="center" diff --git a/res/values/styles.xml b/res/values/styles.xml index 353daac..69cabdb 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -192,6 +192,7 @@        <style name="TouchModeListItem" parent="ListItemContent">          <item name="android:focusableInTouchMode">true</item> +        <item name="android:descendantFocusability">afterDescendants</item>      </style>        <style name="RealListItem" parent="ListItemContent"> diff --git a/src/com/togic/settings/fragment/CitySettings.java b/src/com/togic/settings/fragment/CitySettings.java index f5e9159..3c56cd1 100644 --- a/src/com/togic/settings/fragment/CitySettings.java +++ b/src/com/togic/settings/fragment/CitySettings.java @@ -25,11 +25,13 @@ import android.content.ContentResolver;  import android.content.Context;  import android.content.Intent;  import android.os.Bundle; +import android.view.KeyEvent;  import android.view.LayoutInflater;  import android.view.View;  import android.view.ViewGroup;  import android.widget.AdapterView;  import android.widget.AdapterView.OnItemClickListener; +import android.view.View.OnKeyListener;  import android.widget.ArrayAdapter;  import android.widget.ListView;  import android.widget.TextView; @@ -44,7 +46,8 @@ import com.togic.settings.util.CitysUtil.ProvinceInfo;  /**   * @author mountains.liu@togic.com @date 2012-11-17   */ -public class CitySettings extends Fragment implements OnItemClickListener { +public class CitySettings extends Fragment implements OnItemClickListener, +        OnKeyListener {        public static final int REQ_CODE_CITYS = 0x0001;   @@ -104,6 +107,7 @@ public class CitySettings extends Fragment implements OnItemClickListener {          CitysUtil.queryProvinces(mResolver, provs);          mProvinces.setAdapter(mAdapter = new ProvinceAdapter(mActivity, provs));          mProvinces.setOnItemClickListener(this); +        mProvinces.setOnKeyListener(this);      }        private void handleResult(CityInfo city) { @@ -152,4 +156,14 @@ public class CitySettings extends Fragment implements OnItemClickListener {              return convertView;          }      } + +    public boolean onKey(View v, int keyCode, KeyEvent event) { +        if (event.getAction() == KeyEvent.ACTION_DOWN) { +            if (keyCode == KeyEvent.KEYCODE_DPAD_UP +                    && mProvinces.getSelectedItemPosition() == 0) { +                return true; +            } +        } +        return false; +    }  } diff --git a/src/com/togic/settings/fragment/LanguageSettings.java b/src/com/togic/settings/fragment/LanguageSettings.java index 61b43fd..33ba27d 100644 --- a/src/com/togic/settings/fragment/LanguageSettings.java +++ b/src/com/togic/settings/fragment/LanguageSettings.java @@ -26,8 +26,10 @@ import android.content.Context;  import android.content.Intent;  import android.os.Bundle;  import android.provider.Settings; +import android.view.KeyEvent;  import android.view.LayoutInflater;  import android.view.View; +import android.view.View.OnKeyListener;  import android.view.ViewGroup;  import android.view.inputmethod.InputMethodInfo;  import android.view.inputmethod.InputMethodManager; @@ -40,11 +42,12 @@ import android.widget.TextView;  import com.togic.settings.R;  import com.togic.settings.dialog.KeyboardSelectDialog;  import com.togic.settings.dialog.LanguagesSelectDialog; +import com.togic.settings.util.LogUtil;    /**   * @author mountains.liu@togic.com @date 2012-11-17   */ -public class LanguageSettings extends Fragment { +public class LanguageSettings extends Fragment implements OnKeyListener {        private final static int LANGUAGE_SETTING = 0;   @@ -86,14 +89,17 @@ public class LanguageSettings extends Fragment {          mLanguageList = (ListView) view.findViewById(R.id.language_list);          mMethodList = (ListView) view.findViewById(R.id.method_list);          ArrayList<String> languageLists = new ArrayList<String>(2); -        languageLists.add(mActivity.getResources().getString(R.string.language_setting)); -        languageLists.add(mActivity.getResources().getString(R.string.update_input_method)); +        languageLists.add(mActivity.getResources().getString( +                R.string.language_setting)); +        languageLists.add(mActivity.getResources().getString( +                R.string.update_input_method));          ArrayList<String> methodLists = onCreateIMM();          mLanguageList.setAdapter(mAdapter = new LanguageAdapter(mActivity,                  languageLists));          mMethodList.setAdapter(mAdapter = new LanguageAdapter(mActivity,                  methodLists)); - +        mMethodList.setOnKeyListener(this); +        mLanguageList.setOnKeyListener(this);      }        private ArrayList<String> onCreateIMM() { @@ -193,4 +199,21 @@ public class LanguageSettings extends Fragment {          });      }   +    public boolean onKey(View v, int keyCode, KeyEvent event) { +        if (event.getAction() == KeyEvent.ACTION_DOWN) { +            if (v == mMethodList) { +                if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN +                        && mMethodList.getSelectedItemPosition() == mMethodList +                                .getCount() - 1) { +                    return true; +                } +            } else if (v == mLanguageList) { +                if (keyCode == KeyEvent.KEYCODE_DPAD_UP +                        && mLanguageList.getSelectedItemPosition() == 0) { +                    return true; +                } +            } +        } +        return false; +    }  } diff --git a/src/com/togic/settings/view/AppsList.java b/src/com/togic/settings/view/AppsList.java index 31d15c4..4d85a7a 100644 --- a/src/com/togic/settings/view/AppsList.java +++ b/src/com/togic/settings/view/AppsList.java @@ -38,8 +38,10 @@ import android.os.Bundle;  import android.os.Handler;  import android.util.AttributeSet;  import android.view.InflateException; +import android.view.KeyEvent;  import android.view.LayoutInflater;  import android.view.View; +import android.view.View.OnKeyListener;;  import android.view.ViewGroup;  import android.widget.AdapterView;  import android.widget.AdapterView.OnItemClickListener; @@ -51,7 +53,7 @@ import android.widget.RelativeLayout;   * @author mountains.liu@togic.com @date 2012-11-26   */  public class AppsList extends RelativeLayout implements PackageWatcher, -        OnItemClickListener { +        OnItemClickListener ,OnKeyListener{        public static final int FILTER_UNKNOWN = -1;      public static final int FILTER_ALL = 0; @@ -102,6 +104,7 @@ public class AppsList extends RelativeLayout implements PackageWatcher,          mAdapter = new AppsAdapter(getContext(), new ArrayList<AppInfo>());          mAppList.setAdapter(mAdapter);          mAppList.setOnItemClickListener(this); +        mAppList.setOnKeyListener(this);      }        private void filterApps(int filter) { @@ -271,4 +274,13 @@ public class AppsList extends RelativeLayout implements PackageWatcher,              return convertView;          }      } + +    public boolean onKey(View v, int keyCode, KeyEvent event) { +        if (event.getAction() == KeyEvent.ACTION_DOWN) { +            if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){ +                return true; +            } +        } +        return false; +    }  } diff --git a/src/com/togic/settings/view/ButtonItem.java b/src/com/togic/settings/view/ButtonItem.java new file mode 100644 index 0000000..9d55a25 --- /dev/null +++ b/src/com/togic/settings/view/ButtonItem.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2012 Togic Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.togic.settings.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Button; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; + +public class ButtonItem extends Button implements OnKeyListener { + +    public ButtonItem(Context context, AttributeSet attrs, int defStyle) { +        super(context, attrs, defStyle); +        setOnKeyListener(this); +    } + +    public ButtonItem(Context context, AttributeSet attrs) { +        this(context, attrs, 0); +    } + +    public boolean onKey(View v, int keyCode, KeyEvent event) { +        if (event.getAction() == KeyEvent.ACTION_DOWN) { +            if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { +                return true; +            } +        } +        return false; +    } + +} diff --git a/src/com/togic/settings/view/ListItem.java b/src/com/togic/settings/view/ListItem.java index f2aeb4c..cfd684c 100644 --- a/src/com/togic/settings/view/ListItem.java +++ b/src/com/togic/settings/view/ListItem.java @@ -21,6 +21,7 @@ import android.content.res.TypedArray;  import android.os.Handler;  import android.text.InputType;  import android.util.AttributeSet; +import android.view.FocusFinder;  import android.view.KeyEvent;  import android.view.View;  import android.view.View.OnClickListener; @@ -90,7 +91,7 @@ public class ListItem extends LinearLayout implements OnClickListener,          if (child == this) {              return true;          } else { -            ViewParent vp = child.getParent() ; +            ViewParent vp = child.getParent();              while (vp != null) {                  if (vp == this) {                      return true; @@ -144,6 +145,8 @@ public class ListItem extends LinearLayout implements OnClickListener,                  return findFocusableViewAndFocus(true);              } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {                  return findFocusableViewAndFocus(false); +            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { +                return true;              }          }          return false; @@ -176,22 +179,31 @@ public class ListItem extends LinearLayout implements OnClickListener,      private boolean findFocusableViewAndFocus(boolean up) {          final ViewGroup parent = (ViewGroup) getParent();          final int idx = parent.indexOfChild(this); +          View child = null;          if (up) {              for (int i = idx - 1; i >= 0; i--) {                  child = parent.getChildAt(i); -                if (child.hasFocusable()) { +                if (child.isShown() && child.hasFocusable()) {                      return child.requestFocus();                  }              } +            final View v = FocusFinder.getInstance().findNextFocus( +                    (ViewGroup) getRootView(), this, View.FOCUS_UP); +            if (v instanceof Header) { +                return true; +            } else if (v != null) { +                return v.requestFocus(); +            }          } else {              final int size = parent.getChildCount();              for (int i = idx + 1; i < size; i++) {                  child = parent.getChildAt(i); -                if (child.hasFocusable()) { +                if (child.isShown() && child.hasFocusable()) {                      return child.requestFocus();                  }              } +            return true;          }          return false;      } diff --git a/src/com/togic/settings/view/MyTabWidget.java b/src/com/togic/settings/view/MyTabWidget.java index 47d8f0f..ccc65a7 100644 --- a/src/com/togic/settings/view/MyTabWidget.java +++ b/src/com/togic/settings/view/MyTabWidget.java @@ -35,6 +35,32 @@ public class MyTabWidget extends TabWidget {        private Drawable mDivider;   +    private View mRootView; +    private boolean mFocusFromOutside = false; +    private int mCurrTabIndex = -1; + +    private final OnFocusChangeListener mFocusListener = new OnFocusChangeListener() { +        public void onFocusChange(View v, boolean hasFocus) { +            if (!hasFocus) { +                return; +            } + +            if (!mFocusFromOutside) { +                // just call the OnFocusChangeListener which is set in +                // TabWidget. The OnFocusChangeListener is TabWidget itself. +                MyTabWidget.super.onFocusChange(v, hasFocus); +                return; +            } + +            final View tab = getCurrentTabView(); +            if (tab != null) { +                // find current tab and gain focus. +                tab.requestFocus(); +            } +        } +    }; + +      public MyTabWidget(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          mDivider = getResources().getDrawable(R.drawable.divider); @@ -53,6 +79,34 @@ public class MyTabWidget extends TabWidget {          }      }   +    public void requestChildFocus(View child, View focused) { +        View root = mRootView; +        if (root == null) { +            root = mRootView = getRootView(); +        } +        mFocusFromOutside = indexOfChild(root.findFocus()) < 0; + +        super.requestChildFocus(child, focused); +    } + +    public void addView(View child) { +        super.addView(child); + +        child.setOnFocusChangeListener(mFocusListener); +    } + +    public void removeAllViews() { +        super.removeAllViews(); +        mCurrTabIndex = -1; +    } + +    public void setCurrentTab(int index) { +        super.setCurrentTab(index); +        if (index >= 0 || index < getTabCount()) { +            mCurrTabIndex = index; +        } +    } +      private void drawDividersVertical(Canvas canvas) {          final int count = getChildCount();          View child; @@ -83,6 +137,15 @@ public class MyTabWidget extends TabWidget {          }      }   +    private View getCurrentTabView() { +        final int index = mCurrTabIndex; +        if (index >= 0 || index < getTabCount()) { +            return getChildTabViewAt(index); +        } else { +            return null; +        } +    } +      private void drawHorizontalDivider(Canvas canvas, int top) {          mDivider.setBounds(getPaddingLeft(), top, getWidth()        
相关文章
相关标签/搜索