1

我有一个 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。

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


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


芝士男爵:

这是支持性信息,可帮助说明如果我的解决方案中的一个视图未包装在其关联布局文件中的 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.
4

2 回答 2

0

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

注意:这仅用于存档目的,可能会帮助任何未来的读者解决此问题。我不会接受这个作为我的答案,并且仍然愿意寻求帮助(再次感谢)。


dalvik.system.VMStack.getThreadStackTrace(Native Method) java.lang.Thread.getStackTrace(Thread.java:591) appname.droid.views.EditText2.n_onFocusChanged(Native Method) 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章、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) 安卓。 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(Native Method) java.lang.reflect.Method.invoke(Method.java:511) com .android.internal.os.ZygoteInit$MethodAndArgsCaller。运行(ZygoteInit.java:784)com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)dalvik.system.NativeStart.main(本机方法)

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;
                    }
                }
            }
        }

        ...
    }

    ...
}
于 2013-03-01T17:46:50.547 回答
0

我找到的解决方案并不简单,但它就足够了,而且开销也不大。

因为 Android 的默认行为是为最子视图提供触摸/单击事件,在这种情况下是 EditText 的,我必须继承 EditText 并覆盖它们的 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 通信(另一个接口可以声明片段实现,以便 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 以便可以覆盖在 RecordNoteBox 中组成的 EditText 的 OnTouchEvent,从而有机会向 EditText 没有焦点的包含 ViewPager 发出信号。无法使用 SetCurrentItem(),因为我使用的是半屏 ViewPager 页面(在 ViewPagerAdapter 中为 PageWidth 返回 0.5f),当前位于右侧的任何页面最终都会在调用 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);
        }
    }
}

然后,在具有 EditText 的片段的 OnCreateView 中,我将设置 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);
    }

}

其中布局文件定义如下

Fragment.axml(片段主要布局之一):

  ...
  <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 是 View 的子类,所以我可以弄清楚)。

<?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>
于 2013-07-01T21:05:19.180 回答