为啥 Android TabHost 从 TextView 中窃取焦点?

Posted

技术标签:

【中文标题】为啥 Android TabHost 从 TextView 中窃取焦点?【英文标题】:Why is Android TabHost stealing focus from a TextView?为什么 Android TabHost 从 TextView 中窃取焦点? 【发布时间】:2010-10-21 15:25:11 【问题描述】:

我有一个使用以下布局的应用程序:

alt text http://img15.imageshack.us/img15/238/screenshot003xbo.png

当应用程序启动时,焦点在第一个 TextView 上,但如果您尝试在其中键入任何字母,焦点将直接转到选项卡。看来fighting with this issue不止我一个,可能和以下有关:

http://groups.google.com/group/android-developers/browse_thread/thread/435791bbd6c550a/8022183887f38f4f?lnk=gst&q=tabs+focus#8022183887f38f4f

不管怎样,你知道为什么会这样吗?当然,任何解决方法都将不胜感激。


我在下面发布代码以避免问题过多:

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_
    android:layout_>

    <LinearLayout 
          android:padding="5px"
          android:orientation="vertical" 
          android:id="@+id/task_edit_panel"
          android:layout_
          android:layout_
           android:layout_weight="50" >

        <LinearLayout android:orientation="vertical"
            android:layout_
            android:layout_>

            <TextView android:layout_
                android:layout_ 
                android:text="@string/title" 
                android:textStyle="bold" />

            <EditText android:id="@+id/title" 
              android:layout_
                android:layout_ />

        </LinearLayout>

        <TabHost android:id="@+id/edit_item_tab_host"
                android:layout_
                android:layout_> 

            <TabWidget android:layout_
                        android:layout_ 
                        android:id="@android:id/tabs" /> 

            <FrameLayout
              android:id="@android:id/tabcontent"
              android:layout_
              android:layout_
              android:paddingTop="65px"> <!--  you need that if you don't want the tab content to overflow --> 

              <LinearLayout
                   android:id="@+id/edit_item_date_tab"
                   android:orientation="vertical"
                    android:layout_
                    android:layout_
                    android:padding="5px" > 

                    <TextView android:layout_
                            android:layout_ 
                            android:text="date" 
                             android:textStyle="bold" />

                </LinearLayout>

                <LinearLayout
                   android:id="@+id/edit_item_geocontext_tab"
                   android:orientation="vertical"
                    android:layout_
                    android:layout_
                    android:padding="5px" > 

                <TextView android:layout_
                            android:layout_ 
                            android:text="lieu" 
                             android:textStyle="bold" />

                </LinearLayout>

                <LinearLayout
                   android:id="@+id/edit_item_text_tab"
                   android:orientation="vertical"
                    android:layout_
                    android:layout_
                     android:padding="5px"> 

                <EditText android:id="@+id/details" 
                        android:layout_
                        android:layout_
                        android:scrollbars="vertical" />

                </LinearLayout>

            </FrameLayout>

        </TabHost>

    </LinearLayout>

    <!-- Bottom pannel with "add item" button -->
    <LinearLayout 
          android:padding="5px"
          android:orientation="horizontal" 
          android:layout_weight="1"
          android:id="@+id/task_edit_panel"
          android:layout_
          android:layout_
          android:background="#E7E7E7" >

          <!--  Let the height set to fill_parent until we find a better way for the layout  -->
          <Button android:id="@+id/item_edit_ok_button"
                android:layout_
                android:layout_
                android:layout_gravity="bottom"
                android:text="@string/ok"
                style="?android:attr/buttonStyleSmall"
                android:layout_weight="1" />

           <Button android:id="@+id/item_edit_cancel_button"
                android:layout_
                android:layout_
                android:layout_gravity="bottom"
                android:text="@string/cancel"
                style="?android:attr/buttonStyleSmall"
                android:layout_weight="1" />

    </LinearLayout>

</LinearLayout>

还有 Java 代码:

    TabHost tab_host = (TabHost) findViewById(R.id.edit_item_tab_host);
    // don't forget this setup before adding tabs from a tabhost using a xml view or you'll get an nullpointer exception
    tab_host.setup(); 

    TabSpec ts1 = tab_host.newTabSpec("TAB_DATE");
    ts1.setIndicator(getString(R.string.when), getResources().getDrawable(R.drawable.ic_dialog_time));
    ts1.setContent(R.id.edit_item_date_tab);
    tab_host.addTab(ts1);

    TabSpec ts2 = tab_host.newTabSpec("TAB_GEO");
    ts2.setIndicator(getString(R.string.where),  getResources().getDrawable(R.drawable.ic_dialog_map));
    ts2.setContent(R.id.edit_item_geocontext_tab);
    tab_host.addTab(ts2);

    TabSpec ts3 = tab_host.newTabSpec("TAB_TEXT");
    ts3.setIndicator(getString(R.string.what),  getResources().getDrawable(R.drawable.ic_menu_edit));
    ts3.setContent(R.id.edit_item_text_tab);
    tab_host.addTab(ts3);

    tab_host.setCurrentTab(0);

【问题讨论】:

【参考方案1】:

好吧,这绝对是一个错误:http://code.google.com/p/android/issues/detail?id=2516。

希望它会在下一个版本中得到修复,因为对于具有高级布局的复杂应用来说,这是一个非常烦人的问题。

【讨论】:

【参考方案2】:

我在使用 HoneyComb 时遇到了同样的问题,但找到了一个非常简单的解决方案。所以我认为有人分享我的经验会有所帮助。每次单击选项卡时,焦点都在编辑文本上,您实际上可以使用硬键盘键入,但永远不会弹出软键盘。即使使用以下代码,它也没有解决问题:

input1.requestFocusFromTouch();
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(input1, InputMethodManager.SHOW_FORCED);

解决方案: 在您处理 Tabs 的主类中,只需在 Java 代码下方编写:

myTabHost.setOnTabChangedListener(new OnTabChangeListener()    
    public void onTabChanged(String tabID)     
        myTabHost.clearFocus(); 
       
); 

【讨论】:

【参考方案3】:

如果它与您指出的其他错误无关(看起来很可能是),并且如果您在 G1(而不是模拟器)上遇到此问题,我怀疑您的问题是焦点要么在方向改变之前没有被冻结(当你折叠键盘并进入横向模式时),要么在重新创建视图后解冻。您可以尝试覆盖活动的 onSaveInstanceState()onRestoreInstanceState() 方法来保存/恢复焦点。

【讨论】:

【参考方案4】:

这个例子展示了如何解决这个问题:

userNameEditText.setOnTouchListener(new OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                userNameEditText.requestFocusFromTouch();
                return false;
            
        );

【讨论】:

【参考方案5】:

添加所有规范后,将 requestFocus 方法添加到 java 文件中的编辑文本

【讨论】:

您的意思是解决方案是从EditText 派生一个类,覆盖requestFocus 方法并在构建UI 时使用它而不是标准EditText

以上是关于为啥 Android TabHost 从 TextView 中窃取焦点?的主要内容,如果未能解决你的问题,请参考以下文章

Android TabHost 实现Tab切换

TabHost实现简单Tab切换

Android学习笔记(30):选项卡TabHost

tabhost使用

转载《Android-TabHost 选项卡功能用法详解》

Android-自定义TabHost