ViewPager焦点问题

本文关键字:问题 焦点 ViewPager | 更新日期: 2023-09-27 18:01:40

我有一个ViewPager,包含4个片段/面板,每个半宽度的景观屏幕。

 _______________ _______________ _______________ _______________
|1              |2              |3              |4              |
|               |               |               |               |
|               |               |  ___________  |  ___________  |
|               |               | | EditText1 | | | EditText2 | |
|               |               | |___________| | |___________| |
|_______________|_______________|_______________|_______________|

面板3和4各有一个单独的EditText。

程序启动时,用户显示屏幕2 &3(他们可以向后滑动看到屏幕1,屏幕4还不存在,直到3上的列表项被选中)。

因此,承载面板的视图(和关联的ViewPager)调用

viewPager.SetCurrentItem(PANEL3,true);   // const int PANEL3 = 2;  - zero offset

导致2 &3要显示,并给3焦点(这给了EditText1焦点)。

当用户在3上选择一些东西时,会导致4滑动进来(所以现在3 &4人正在展示);在宿主视图

中进行另一个调用
viewPager.SetCurrentItem(PANEL4,true);    // const int PANEL4 = 3;  - zero offset

使现在面板4获得焦点(这给了EditText2焦点)。


问题是:

与面板3 &4显示,其中EditText2有焦点,如果我然后点击到EditText1,这导致软键盘弹出,焦点将恢复到EditText2(光标在EditText2和任何键入进入它)。

我需要知道是什么导致焦点恢复到EditText2。

我推测对viewpage . setcontentview (PANEL4)的调用导致面板焦点状态保留在ViewPager某处,当软键盘弹出并导致一些"刷新"事件触发时,ViewPager正在恢复该焦点状态(这是PANEL4),尽管我不确定。我在主机视图和每个面板中做了很多打印输出,软键盘弹出不会导致任何标准生命周期事件被触发,但我知道viewPager的OnLayout确实会触发。


欢迎任何帮助或见解,谢谢。


Cheesebaron:

这是支持性信息,有助于说明如果我的解决方案中的一个视图没有在其相关布局文件中的ViewGroup (LinearLayout)中包装,则会发生膨胀问题。

如果PagedFragmentRecordNoteBoxInput没有被包装在LinearLayout中,我们有

<?xml version="1.0" encoding="utf-8"?>
<FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.PagedFragmentRecordNoteBoxInput
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fi_record_note_box_input"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFFFF"
    android:gravity="top"
    android:textSize="20sp"
    android:textColor="#FF000000"
    android:layout_margin="20dip"/>

PagedFragmentRecordNoteBox中的膨胀代码更改为

protected override RecordNoteBoxInput InstantiateInput()
{
    View v = _inflater.Inflate(Resource.Layout.PagedFragmentRecordNoteBoxInput, null);
    _pagedFragmentFieldInput = (PagedFragmentRecordNoteBoxInput) v;
    _pagedFragmentFieldInput.OuterClass = this;
    return (RecordNoteBoxInput)_pagedFragmentFieldInput;
}

然后产生异常:

07-02 16:21:32.494: I/MonoDroid(18642): UNHANDLED EXCEPTION: Android.Views.InflateException: Exception of type 'Android.Views.InflateException' was thrown.
07-02 16:21:32.494: I/MonoDroid(18642): at Android.Runtime.JNIEnv.CallObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
07-02 16:21:32.494: I/MonoDroid(18642): at Android.Views.LayoutInflater.Inflate (int,Android.Views.ViewGroup) <0x0018f>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.InstantiateInput () <0x0002b>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox.Init (Android.Content.Context) <0x00063>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x0002f>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x00023>
07-02 16:21:32.494: I/MonoDroid(18642): at (wrapper dynamic-method) object.705e129e-2c0d-42db-87f7-db1842b85d7c (intptr,object[]) <0x0005f>
07-02 16:21:32.494: I/MonoDroid(18642): at Java.Interop.TypeManager.n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) <0x000f7>
07-02 16:21:32.494: I/MonoDroid(18642): at (wrapper native-to-managed) Java.Interop.TypeManager.n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) <0x0006f>
07-02 16:21:32.494: I/MonoDroid(18642): at (wrapper delegate-invoke) <Module>.invoke_intptr__this___intptr_intptr_intptr_JValue[] (intptr,intptr,intptr,Android.Runtime.JValue[]) <0x000ab>
07-02 16:21:32.494: I/MonoDroid(18642): at Android.Runtime.JNIEnv.CallObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00053>
07-02 16:21:32.494: I/MonoDroid(18642): at Android.Views.LayoutInflater.Inflate (int,Android.Views.ViewGroup,bool) <0x001f3>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.ParcelRecordDetailInspectionView.Render () <0x0002f>
07-02 16:21:32.494: I/MonoDroid(18642): at FieldInspection.Droid.Views.ParcelRecordDetailInspectionView.OnCreateView (Android.Views.LayoutInflater,Android.Views.ViewGroup,Android.OS.Bundle) <0x000af>
07-02 16:21:32.494: I/MonoDroid(18642): at Android.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) <0x0009f>
07-02 16:21:32.494: I/MonoDroid(18642): at (wrapper dynamic-method) object.5d994140-166d-44ce-ac16-71f1e1698262 (intptr,intptr,intptr,intptr,intptr) <0x0005b>
07-02 16:21:32.494: I/MonoDroid(18642):   --- End of managed exception stack trace ---
07-02 16:21:32.494: I/MonoDroid(18642): android.view.InflateException: Binary XML file line #5: Error inflating class FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.PagedFragmentRecordNoteBoxInput
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:691)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
07-02 16:21:32.494: I/MonoDroid(18642):     at mono.android.TypeManager.n_activate(Native Method)
07-02 16:21:32.494: I/MonoDroid(18642):     at mono.android.TypeManager.Activate(TypeManager.java:7)
07-02 16:21:32.494: I/MonoDroid(18642):     at fieldinspection.droid.views.custom.PagedFragmentRecordNoteBox.<init>(PagedFragmentRecordNoteBox.java:29)
07-02 16:21:32.494: I/MonoDroid(18642):     at java.lang.reflect.Constructor.constructNative(Native Method)
07-02 16:21:32.494: I/MonoDroid(18642):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.createView(LayoutInflater.java:586)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.parseInclude(LayoutInflater.java:800)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:729)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:742)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:742)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:742)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
07-02 16:21:32.494: I/MonoDroid(18642):     at fieldinspection.droid.views.ParcelRecordDetailInspectionView.n_onCreateView(Native Method)
07-02 16:21:32.494: I/MonoDroid(18642):     at fieldinspection.droid.views.ParcelRecordDetailInspectionView.onCreateView(ParcelRecordDetailInspectionView.java:52)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:828)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1032)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.app.BackStackRecord.run(BackStackRecord.java:622)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1382)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:437)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.support.v13.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:167)
07-02 16:21:32.494: I/MonoDroid(18642):     at android.supp
07-02 16:21:32.504: E/mono(18642): Unhandled Exception:
07-02 16:21:32.504: E/mono(18642): Android.Views.InflateException: Exception of type 'Android.Views.InflateException' was thrown.
07-02 16:21:32.504: E/mono(18642): at Android.Runtime.JNIEnv.CallObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
07-02 16:21:32.504: E/mono(18642): at Android.Views.LayoutInflater.Inflate (int,Android.Views.ViewGroup) <0x0018f>
07-02 16:21:32.504: E/mono(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.InstantiateInput () <0x0002b>
07-02 16:21:32.504: E/mono(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox.Init (Android.Content.Context) <0x00063>
07-02 16:21:32.504: E/mono(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x0002f>
07-02 16:21:32.504: E/mono(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x00023>
07-02 16:21:32.504: E/mono(18642): at (wrapper dynamic-method) object.705e129e-2c0d-42db-87f7-db1842b85d7c (intptr,object[]) <0x0005f>
07-02 16:21:32.504: E/mono(18642): at Java.Interop.TypeManager.n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) <0x000f7>
07-02 16:21:32.504: E/mono(18642): at (wrapper native-to-managed) Java.Interop.TypeManager.n_Activate (intptr,intptr,intptr,intptr,
07-02 16:21:32.504: I/mono(18642): [ERROR] FATAL UNHANDLED EXCEPTION: Android.Views.InflateException: Exception of type 'Android.Views.InflateException' was thrown.
07-02 16:21:32.504: I/mono(18642): at Android.Runtime.JNIEnv.CallObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
07-02 16:21:32.504: I/mono(18642): at Android.Views.LayoutInflater.Inflate (int,Android.Views.ViewGroup) <0x0018f>
07-02 16:21:32.504: I/mono(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.InstantiateInput () <0x0002b>
07-02 16:21:32.504: I/mono(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox.Init (Android.Content.Context) <0x00063>
07-02 16:21:32.504: I/mono(18642): at FieldInspection.Droid.Views.Custom.RecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x0002f>
07-02 16:21:32.504: I/mono(18642): at FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox..ctor (Android.Content.Context,Android.Util.IAttributeSet) <0x00023>
07-02 16:21:32.504: I/mono(18642): at (wrapper dynamic-method) object.705e129e-2c0d-42db-87f7-db1842b85d7c (intptr,object[]) <0x0005f>
07-02 16:21:32.504: I/mono(18642): at Java.Interop.TypeManager.n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) <0x000f7>
07-02 16:21:32.504: I/mono(18642): at (wrapper native-to-managed) Java.Interop.TypeManager.n_Activate (intptr,intptr,i
07-02 16:21:32.524: W/InputDispatcher(215): channel '41b69d78 net.monocross.fieldinspection/fieldinspection.droid.FieldInspectionMain (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
07-02 16:21:32.524: E/InputDispatcher(215): channel '41b69d78 net.monocross.fieldinspection/fieldinspection.droid.FieldInspectionMain (server)' ~ Channel is unrecoverably broken and will be disposed!
07-02 16:21:32.524: W/InputDispatcher(215): Attempted to unregister already unregistered input channel '41b69d78 net.monocross.fieldinspection/fieldinspection.droid.FieldInspectionMain (server)'
07-02 16:21:32.524: D/Zygote(116): Process 18642 exited cleanly (1)
07-02 16:21:32.524: W/InputDispatcher(215): channel '41aef860 net.monocross.fieldinspection/fieldinspection.droid.views.CalendarView (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
07-02 16:21:32.524: E/InputDispatcher(215): channel '41aef860 net.monocross.fieldinspection/fieldinspection.droid.views.CalendarView (server)' ~ Channel is unrecoverably broken and will be disposed!
07-02 16:21:32.524: W/InputDispatcher(215): Attempted to unregister already unregistered input channel '41aef860 net.monocross.fieldinspection/fieldinspection.droid.views.CalendarView (server)'
07-02 16:21:32.524: I/ActivityManager(215): Process net.monocross.fieldinspection (pid 18642) has died.

ViewPager焦点问题

我的答案就在这个堆栈跟踪中,这是来自上面提到的EditText子类EditText2的OnFocusChange()覆盖(跟踪这个的好时机):

注意:这只是为了存档的目的,可能会帮助将来的读者解决这个问题。我不会接受这个作为我的答案,我仍然愿意寻求帮助(再次感谢)。


dalvik.system.VMStack。getThreadStackTrace(本地方法)java.lang.Thread.getStackTrace (Thread.java: 591)appname.droid.views.EditText2。n_onFocusChanged(本地方法)appname.droid.views.EditText2.onFocusChanged (EditText2.java: 53)android.view.View.handleFocusGainInternal (View.java: 3680)android.view.View.requestFocus (View.java: 5373)android.view.ViewGroup.onRequestFocusInDescendants (ViewGroup.java: 2154)android.view.ViewGroup.requestFocus (ViewGroup.java: 2110)android.view.ViewGroup.onRequestFocusInDescendants (ViewGroup.java: 2154)android.view.ViewGroup.requestFocus (ViewGroup.java: 2110)android.view.ViewGroup.onRequestFocusInDescendants (ViewGroup.java: 2154)android.view.ViewGroup.requestFocus (ViewGroup.java: 2110)android.view.ViewGroup.onRequestFocusInDescendants (ViewGroup.java: 2154)android.view.ViewGroup.requestFocus (ViewGroup.java: 2113)android.view.ViewGroup.onRequestFocusInDescendants (ViewGroup.java: 2154)android.view.ViewGroup.requestFocus (ViewGroup.java: 2110) android.view.View.requestFocus (View.java: 5323) android.support.v4.view.ViewPager.populate (ViewPager.java: 1051) android.support.v4.view.ViewPager.populate (ViewPager.java: 881)android.support.v4.view.ViewPager.onMeasure (ViewPager.java: 1366)android.view.View.measure (View.java: 12728)android.view.ViewGroup.measureChildWithMargins (ViewGroup.java: 4698)android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java: 1369)android.widget.LinearLayout.measureVertical (LinearLayout.java: 660)android.widget.LinearLayout.onMeasure (LinearLayout.java: 553)android.view.View.measure (View.java: 12728)android.view.ViewGroup.measureChildWithMargins (ViewGroup.java: 4698)android.widget.FrameLayout.onMeasure (FrameLayout.java: 293)android.view.View.measure (View.java: 12728)android.view.ViewGroup.measureChildWithMargins (ViewGroup.java: 4698)android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java: 1369)android.widget.LinearLayout.measureVertical (LinearLayout.java: 660)android.widget.LinearLayout.onMeasure (LinearLayout.java: 553)android.view.View.measure (View.java: 12728)android.view.ViewGroup.measureChildWithMargins (ViewGroup.java: 4698)android.widget.FrameLayout.onMeasure (FrameLayout.java: 293)com.android.internal.policy.impl.PhoneWindow DecorView.onMeasure美元(PhoneWindow.java: 2092)android.view.View.measure (View.java: 12728)android.view.ViewRootImpl.performTraversals (ViewRootImpl.java: 1064)android.view.ViewRootImpl.handleMessage (ViewRootImpl.java: 2442)android.os.Handler.dispatchMessage (Handler.java: 99)android.os.Looper.loop (Looper.java: 137)android.app.ActivityThread.main (ActivityThread.java: 4424)java.lang.reflect.Method。invokeNative(本地方法)java.lang.reflect.Method.invoke (Method.java: 511)com.android.internal.os.ZygoteInit MethodAndArgsCaller.run美元(ZygoteInit.java: 784)com.android.internal.os.ZygoteInit.main (ZygoteInit.java: 551)dalvik.system.NativeStart。主要(本地方法)

public class ViewPager extends ViewGroup 
{
    ...
    void populate 
    {
        ...
        if (hasFocus()) {
            View currentFocused = findFocus();
            ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
            if (ii == null || ii.position != mCurItem) {
                for (int i=0; i<getChildCount(); i++) {
                View child = getChildAt(i);
                ii = infoForChild(child);
                if (ii != null && ii.position == mCurItem) {
                    if (child.requestFocus(FOCUS_FORWARD)) {
                        break;
                    }
                }
            }
        }
        ...
    }
    ...
}

我找到的解决方案不是微不足道的,但它足够了,并且没有太多的开销。

因为Android的默认行为是给最子视图一个触摸/点击事件,在这种情况下,在EditText's,我不得不子类化EditText's和覆盖他们的OnTouchEvent成员。

在这种情况下委派是不够的

myEditText.Touch += EditTextTouchEventHandler;

,因为我仍然想要EditText(内置)触摸事件的默认行为(它做了一些很好的事情,比如将光标定位在用户触摸的地方,而不仅仅是在文本框的开头)。

在OnTouchEvent中,保存这个EditText的片段的视图页被通知这个点击事件,并且EditText聚焦被手动处理(所以当任何刷新发生时-即键盘弹出-因此RequestFocus被触发,最后点击的EditText将不会失去焦点(如预期的那样)。通信是通过Android推荐的片段"回调"的父-监听器模式完成的,即

另外,ViewPager的RequestChildFocus方法必须被重写,这样事件才能被截获和吃掉。在它的位置上,一个次要的RequestChildFocus2方法被手动调用,它反过来调用基类RequestChildFocus。

包含ViewPager定义并实现接口的Activity

public interface IFragmentToViewPagerEvent
{
    void ParcelRecordFieldClickEvent(Fragment child, View focused);
}

并且每个片段将保存一个对活动的引用,转换到这个接口,因此片段可以通过接口方法与ViewPager通信(另一个接口可以声明Fragments实现,这样ViewPager就可以调用片段-然后通信的两个方向都被覆盖)。

private ParcelView.IFragmentToViewPagerEvent _fragmentToViewPagerEvent;
public override void OnAttach(Activity activity)
{
    base.OnAttach(activity);
    _fragmentToViewPagerEvent = (ParcelView.IFragmentToViewPagerEvent) activity;
}

子类的样子如下:

RecordNoteBoxInput是一个自定义类,创建为EditText,它将被放置在选项卡中,并展开填充包含它的制表符,四周使用统一宽度的边框。

public class RecordNoteBoxInput : EditText
{
    // sometime u need this, other times you don't - mono's missing nuts that android don't
    //public RecordNoteBoxInput(IntPtr jRef, JniHandleOwnership handle) : base(jRef, handle) { }
    public RecordNoteBoxInput(Context context) : base(context) { }
    public RecordNoteBoxInput(Context context, IAttributeSet attributes) : base(context, attributes) { }
    public RecordNoteBoxInput(Context context, IAttributeSet attributes, int defStyle) : base(context, attributes, defStyle) { }
}
public class RecordNoteBox : LinearLayout
{
    protected Context _context;
    protected LayoutInflater _inflater;
    protected RecordNoteBoxInput _inputFiled;
    public RecordNoteBoxInput Input
    {
        get { return _inputFiled; }
        set { _inputFiled = value; }
    }
    protected virtual RecordNoteBoxInput InstantiateInput()
    {
        return (RecordNoteBoxInput)_inflater.Inflate(Resource.Layout.RecordNoteBoxInput, this, false);
    }
    protected void Init(Context context)
    {
        _context = context;
        _inflater = LayoutInflater.From(context);
        _inputFiled = InstantiateInput(); 
        this.AddView(_inputFiled);
    }
    // sometime u need this, other times you don't - mono's missing nuts that android don't
    //public RecordNoteBox(IntPtr jRef, JniHandleOwnership handle) : base(jRef, handle) { }
    public RecordNoteBox(Context context) : base(context) { Init(context); }
    public RecordNoteBox(Context context, IAttributeSet attributes) : base(context, attributes) { Init(context); }
    public RecordNoteBox(Context context, IAttributeSet attributes, int defStyle) : base(context, attributes, defStyle) { Init(context); }
}

PagedFragmentRecordNoteBox被创建,以便EditText的OnTouchEvent组成在RecordNoteBox内可以被重写,允许有机会向包含EditText没有焦点的ViewPager发出信号。SetCurrentItem()不能使用,因为我使用半屏幕ViewPager页面(在ViewPagerAdapter返回0.5f的PageWidth),任何页面,目前是在右边将最终被自动移动到左边调用SetCurrentItem,因为这是一个ViewPager的默认行为,我不愿意重写这个函数。此外,这个函数有一个内部/私有版本,如果不重写整个ViewPager类,我就无法控制它。

public class PagedFragmentRecordNoteBox : RecordNoteBox
{
    public Fragment ParentFragment { get; set; }
    public RecordView.IFragmentToViewPagerEvent PagerListener { get; set; }
    private PagedFragmentRecordNoteBoxInput _pagedFragmentFieldInput;
    // sometime u need this, other times you don't - mono's missing nuts that android don't
    //public PagedFragmentRecordNoteBox(IntPtr jRef, JniHandleOwnership handle) : base(jRef, handle) { }
    public PagedFragmentRecordNoteBox(Context context) : base(context) { }
    public PagedFragmentRecordNoteBox(Context context, IAttributeSet attributes) : base(context, attributes) { }
    public PagedFragmentRecordNoteBox(Context context, IAttributeSet attributes, int defStyle) : base(context, attributes, defStyle) { }
    protected override RecordNoteBoxInput InstantiateInput()
    {
        // Since I was getting inflation exception when the layout file 
        // PagedFragmentRecordRecordNoteBoxInput.axml had only a single, not wrapped in any ViewGroup, I had to 
        // wrap it up in a linear layout (whatever). Since this view will be added somewhere else, it needs to 
        // be removed from the wrapper (hence the call to RemoveAllViews - comment it out to see what happens).
        //LayoutInflater inflater = (LayoutInflater)_context.ApplicationContext.GetSystemService(Context.LayoutInflaterService);
        View v = _inflater.Inflate(Resource.Layout.PagedFragmentRecordRecordNoteBoxInput, null);
        _pagedFragmentFieldInput = ((ViewGroup)v).FindViewById<PagedFragmentRecordNoteBoxInput>(Resource.Id.fi_record_note_box_input);
        ((ViewGroup)v).RemoveAllViews();
        _pagedFragmentFieldInput.OuterClass = this;
        return (RecordNoteBoxInput)_pagedFragmentFieldInput;
    }
    protected class PagedFragmentRecordNoteBoxInput : RecordNoteBoxInput
    {
        public PagedFragmentRecordNoteBox OuterClass { get; set; }
        private Context _context { get; set; }
        // sometime u need this, other times you don't - mono's missing nuts that android don't
        //public PagedFragmentRecordNoteBoxInput(IntPtr jRef, JniHandleOwnership handle) : base(jRef, handle) { }
        public PagedFragmentRecordNoteBoxInput(Context context) : base(context) { _context = context; }
        public PagedFragmentRecordNoteBoxInput(Context context, IAttributeSet attributes) : base(context, attributes) { _context = context; }
        public PagedFragmentRecordNoteBoxInput(Context context, IAttributeSet attributes, int defStyle) : base(context, attributes, defStyle) { _context = context; }
        public override bool OnTouchEvent(MotionEvent e)
        {
            OuterClass.PagerListener.ParcelRecordFieldClickEvent(OuterClass.ParentFragment, this);
            return base.OnTouchEvent(e);
        }
    }
}

然后,在OnCreateView的片段有一个EditText,我会设置EditText(或,它的子类)像

_thisView = (ViewGroup) _inflater.Inflate(Resource.Layout.Record, _container, false);
PagedFragmentRecordNoteBox userNotes = _thisView.FindViewById<PagedFragmentRecordNoteBox>(Resource.Id.ll_record_note_box);
PagedFragmentRecordNoteBox userNotes.ParentFragment = this;
PagedFragmentRecordNoteBox userNotes.PagerListener = _fragmentToViewPagerEvent;

承载ViewPager的主活动看起来像

public class ParcelView : Activity
{
    protected ViewPager _viewPager;
    private List<Android.App.Fragment> _fragments;
    public interface IFragmentToViewPagerEvent
    {
        void ParcelRecordFieldClickEvent(Fragment child, View focused);
    }
    void IFragmentToViewPagerEvent.ParcelRecordFieldClickEvent(Fragment child, View focused)
    {
        _viewPager.RequestChildFocus2(null, focused);
    }   
}

最后需要做的是重写ViewPager的RequestChildFocus()方法,并在请求中吃掉它:

public class ViewPager2 : ViewPager
{
    private view _clearFocused;
    public override void RequestChildFocus(View child, View focused)
    {
        //base.RequestChildFocus(child, focused);
    }
    public void RequestChildFocus2(View child, View focused)
    {            
        if( _clearFocused != null )
        {
            _clearFocused.ClearFocus();
        }
        _clearFocused = focused;
        base.RequestChildFocus(child, focused);
    }
}

,其中布局文件定义如下

片段。axml (fragments的主要布局之一):

  ...
  <TabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/ll_record_detail_tab"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical"
      android:background="#FF200000">
      <FieldInspection.Droid.Views.MyTabWidget
        android:id="@android:id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
      <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        ...
        <include layout="@layout/RecordNoteBox"/>
        ...
      </FrameLayout>
    </LinearLayout>
  </TabHost>
  ...

RecordNoteBox.axml

<?xml version="1.0" encoding="utf-8"?>
<!--fieldinspection.droid.views.custom.RecordNoteBox-->
<fieldinspection.droid.views.custom.PagedFragmentRecordNoteBox
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/ll_record_note_box"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#FF555555">
</fieldinspection.droid.views.custom.PagedFragmentRecordNoteBox>

RecordNotBoxInput.axml

<?xml version="1.0" encoding="utf-8"?>
<fieldinspection.droid.views.custom.FieldInput
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/fi_record_note_box_input"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#FFFFFFFF"
  android:gravity="top"
  android:textSize="20sp"
  android:textColor="#FF000000"
  android:layout_margin="20dip"/> 

PagedFragmentRecordNoteBoxInput。axml -注意它被包装在一个LinearLayout中。这是为了避免通货膨胀的例外。还不确定为什么有些视图需要包装在一个ViewGroup为了膨胀,但他们做(更奇怪的是,ViewGroup是一个子类的视图,所以我可以弄清楚)。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/ll_record_note_box_input_container"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <FieldInspection.Droid.Views.Custom.PagedFragmentRecordNoteBox.PagedFragmentRecordNoteBoxInput
    android:id="@+id/fi_record_note_box_input"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFFFF"
    android:gravity="top"
    android:textSize="20sp"
    android:textColor="#FF000000"
    android:layout_margin="20dip"/>
  </LinearLayout>