【问题标题】:FragmentPagerAdapter Exists Only In Android.Support.V4.App (and not Android.App)FragmentPagerAdapter 仅存在于 Android.Support.V4.App(而不是 Android.App)中
【发布时间】:2019-09-14 21:16:16
【问题描述】:

我在 Android.App 中找不到 FragmentPagerAdapter。

我不想使用 Android.Support.V4.App 中的 Fragment,因为我的目标 API 是 14 及更高版本(Android 4.0 及更高版本)。所以,我只想使用普通的 Android.App.Fragments, 以及相关的类。

我只在 Android.Support.V4.App 中找到它,但这还不够 对我来说 b/c 我正在尝试使用 Android.App.Fragment 的(不是 Android.Support.V4.App.Fragment 的) 并且在Android.App(不是Android.Support.V4.App)中有相关的类,我的代码不会 如果我从支持库中派生出我的寻呼机,则编译, 因为导致 Android.App 和 Android.Support.V4.App 之间的类型不匹配。

就像这里Cannot be cast to android.app.Fragment 的情况一样,是否有一个“普通”寻呼机(PagerAdapter)类我应该使用 FragmentPagerAdapter 或其他东西的位置(就像您从正常的 Activity 派生一样,并且 不是 FragmentActivity,当面向 API 11 或更高版本时)。

这是我正在使用的示例代码(它是位于 https://github.com/xamarin/monodroid-samples/tree/master/Support4 的 MonoDroid 示例中 Support4.sln 解决方案中的 FragmentPagerSupport.cs 文件)。

我已注释掉引用 Android.Support.V4.App 的行并将其替换为 引用 Android.App 的代码。 Android.Support.V4.App 之外没有我能找到的 FramePagerAdapter,我真的需要它。

谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
//using Android.Support.V4.App;
//using Android.Support.V4.View;

namespace Support4
{
    [Activity (Label = "@string/fragment_pager_support")]
    [IntentFilter (new[]{Intent.ActionMain}, Categories = new[]{ "mono.support4demo.sample" })]
    //public class FragmentPagerSupport : FragmentActivity
        public class FragmentPagerSupport : Activity
    {
        const int NUM_ITEMS = 10;
        MyAdapter adapter;
        ViewPager pager;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SetContentView(Resource.Layout.fragment_pager);

            //adapter = new MyAdapter(SupportFragmentManager);
                        adapter = new MyAdapter(FragmentManager);

            pager = FindViewById<ViewPager>(Resource.Id.pager);
            pager.Adapter = adapter;

            var button = FindViewById<Button>(Resource.Id.goto_first);
            button.Click += (sender, e) => {
                pager.CurrentItem = 0;  
            };
            button = FindViewById<Button>(Resource.Id.goto_last);
            button.Click += (sender, e) => {
                pager.CurrentItem = NUM_ITEMS - 1;
            };
        }

                // ?????????????????????????????????????????????????
                // - where is FragmentPagerAdapter 
                // ?????????????????????????????????????????????????

        protected class MyAdapter : FragmentPagerAdapter 
        {
            public MyAdapter(FragmentManager fm) : base(fm)
            {
            }

            public override int Count {
                get {
                    return NUM_ITEMS;
                }
            }

            public override Fragment GetItem (int position)
            {
                return new ArrayListFragment(position);
            }


        }

        protected class ArrayListFragment : ListFragment
        {
            int num;

            public ArrayListFragment()
            {
            }

            public ArrayListFragment(int num)
            {
                var args = new Bundle();
                args.PutInt("num", num);
                Arguments = args;
            }

            public override void OnCreate (Bundle p0)
            {
                base.OnCreate (p0);

                num = Arguments != null ? Arguments.GetInt("num") : 1;
            }

            public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
            {
                var v = inflater.Inflate(Resource.Layout.fragment_pager_list, container, false);
                var tv = v.FindViewById<TextView>(Resource.Id.text);
                tv.Text = "Fragment #" + num;
                return v;
            }

            public override void OnActivityCreated (Bundle p0)
            {
                base.OnActivityCreated (p0);

                ListAdapter = new ArrayAdapter<string>(Activity, Android.Resource.Layout.SimpleListItem1, Cheeses.cheeseStrings);
            }

            public override void OnListItemClick(ListView l, View v, int position, long id) {
                Console.WriteLine ( "Item clicked: " + id);
            }
        }
    }
}

【问题讨论】:

  • android.support.v13.app.FragmentPagerAdapter 中有一个。不确定这是否对您有帮助,但是...
  • PearsonArtPhoto 不确定,因为没有 Android.Support.V13.View 命名空间(无论如何在 MonoDroid 中)。我宁愿根本不使用支持库,但我认为目前还不可能。
  • 看起来 ViewPager 也只存在于支持库中......
  • developer.android.com/reference/android/support/v4/view/… 类概述部分很好地总结了这种困境 - “注意这个类目前处于早期设计和开发阶段。API 可能会在以后的兼容性库更新中发生变化,需要更改应用程序在针对较新版本编译时的源代码。”
  • 另一个来自文档developer.android.com/tools/extras/support-library.html 的摘录“v4 的支持库提供了对 Android 3.0 及更高版本引入的几个类的访问,以及现有类的一些更新版本,甚至是一些当前不支持的 API” t存在于Android平台”。但是,他们为什么会在支持库中专门留下如此重要的片段“API”,如果它的其余部分存在于外部。也许是疏忽?

标签: android android-fragments xamarin.android fragmentpageradapter


【解决方案1】:

android.support.v13.app.FragmentPagerAdapter 中有一个,它应该做你想做的事。它是不支持 Fragment 的 FragmentPagerAdapter。

Android Studio 安装

请添加follow Gradle依赖

dependencies {
    compile 'com.android.support:support-v13:+'
}

【讨论】:

  • 从某种意义上说,您不能在支持库 13 中使用嵌套片段和 getChildFragmentManager(),这是一团糟。
  • 使用 compile 'com.android.support:support-v13:21.0.+' 进行 gradle 构建
  • 我的 android studio 无法解析 import android.support.v13.app.FragmentPagerAdapter; 任何想法?确定已经将 compile 'com.android.support:support-v13:23.1.1' 添加到 gradle
  • support:support-v13 在我的情况下与 support:design 冲突
  • 但现在在 api 27 中已弃用 -> 再次使用 v4 版本。然后我们又遇到了问题,无法使用无支持的库片段
【解决方案2】:

呃,你只需要使用 V13 支持库中的 FragmentPagerAdapter 就可以了

Android.Support.V13.App.FragmentPagerAdapter

然后可以从“普通”库/命名空间中使用所有其他与 Fragment 相关的类,ViewPager 除外,但这没什么大不了的。


这是一个完整的示例(从https://github.com/xamarin/monodroid-samples/ 修改的“Support4”示例):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;

using Java.Lang;

using Android.Support.V4.View;
using Fragment = Android.App.Fragment;

namespace Support4
{
    [Activity (Label = "@string/fragment_pager_support")]
    [IntentFilter (new[]{Intent.ActionMain}, Categories = new[]{ "mono.support4demo.sample" })]
    public class FragmentPagerSupport : Activity
    //public class FragmentPagerSupport : FragmentActivity
    {
        const int NUM_ITEMS = 4;

        protected MyAdapter _pagerAdapter;
        protected ViewPager _viewPager;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SetContentView(Resource.Layout.fragment_pager);

            List<Fragment> fragments = new List<Fragment>();

            // *** MonoDroid 4.2.7 letter case bug *** make's first letter lower.

            //string typeName = typeof(Fragment1).FullName;
            string typeName = "support4." + typeof(Fragment1).Name;

            fragments.Add(Fragment.Instantiate(this, typeName));
            fragments.Add(Fragment.Instantiate(this, typeName));
            fragments.Add(Fragment.Instantiate(this, typeName));
            fragments.Add(Fragment.Instantiate(this, typeName));

            //adapter = new MyAdapter(SupportFragmentManager);
            _pagerAdapter = new MyAdapter(FragmentManager, fragments);

            _viewPager = FindViewById<ViewPager>(Resource.Id.view_pager);
            _viewPager.Adapter = _pagerAdapter;
        }

        public override bool OnTouchEvent(MotionEvent e)
        {
            return base.OnTouchEvent(e);
        }

        protected class MyAdapter : Android.Support.V13.App.FragmentPagerAdapter
        {
            private List<Fragment> _fragments;

            public override Java.Lang.Object  InstantiateItem(View p0, int p1)
            {
                return base.InstantiateItem(p0, p1);
            }

            public MyAdapter(Android.App.FragmentManager fm)
                : base(fm)
            {

            }

            //public MyAdapter(Android.Support.V4.App.FragmentManager fm, List<Android.Support.V4.App.Fragment> fragments)
            //    : base(fm)
            public MyAdapter(FragmentManager fm, List<Fragment> fragments)
                : base(fm)
            {
                _fragments = fragments;
            }

            public override int Count {
                get {
                    return NUM_ITEMS;
                }
            }

            //public override Android.Support.V4.App.Fragment GetItem(int p0)
            public override Fragment GetItem(int p0)
            {
                return _fragments[p0];
            }

            public override float GetPageWidth(int p0)
            {
                //return base.GetPageWidth(p0);
                //base.GetPageWidth(p0);

                return (float)(0.5f);
            }
        }
    }

    //public class Fragment1 : Android.Support.V4.App.Fragment
    public class Fragment1 : Fragment
    {
        int num;

        private static int _colorIndex = 0;
        private static Android.Graphics.Color[] _colors = new[] { Android.Graphics.Color.Aqua, Android.Graphics.Color.DarkViolet,
        Android.Graphics.Color.Coral, Android.Graphics.Color.Bisque};

        public Fragment1()
        {
        }

        public Fragment1(int num)
        {
            var args = new Bundle();
            args.PutInt("num", num);
            Arguments = args;
        }

        public override void OnCreate(Bundle p0)
        {
            base.OnCreate(p0);

            num = Arguments != null ? Arguments.GetInt("num") : 1;
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            View v = inflater.Inflate(Resource.Layout.aaaaa, container, false);

            TextView tv = v.FindViewById<TextView>(Resource.Id.text);
            tv.Text = "# " + _colorIndex;
            tv.SetBackgroundColor(_colors[_colorIndex++]);

            return v;
        }

        public override void OnActivityCreated(Bundle p0)
        {
            base.OnActivityCreated(p0);
        }
    }
}

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project

     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.
-->

<!-- Top-level content view for the simple fragment sample. -->

<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal" android:padding="4dip"
  android:layout_width="match_parent" android:layout_height="match_parent">
  <!--android:gravity="center_horizontal"-->

  <android.support.v4.view.ViewPager
    android:id="@+id/view_pager"
    android:layout_width="700dip"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:background="#FFCCFFFF">

    <!--android:layout_width="match_parent"-->
  </android.support.v4.view.ViewPager>

</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/screen_container"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <TextView android:id="@+id/text"
      android:layout_width="match_parent" android:layout_height="match_parent"
      android:gravity="center_vertical|center_horizontal"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:text="@string/hello_world"
      android:background="#FF335555"/>

</LinearLayout>

【讨论】:

  • 从某种意义上说,您不能在支持库 13 中使用嵌套片段和 getChildFragmentManager(),这是一团糟。
【解决方案3】:

将此依赖项添加到 gradle 依赖项中:

compile 'com.android.support:support-v13:+'

并像这样使用android.support.v13.app.FragmentPagerAdapter(我只是在android studio中修改了官方演示项目:文件→新建→新项目→下一个→下一个→选项卡式活动→下一个→完成):

import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v13.app.FragmentPagerAdapter;
import com.google.android.gms.maps.MapFragment;

/** A simple FragmentPagerAdapter that returns a MapFragment and a PreferenceFragment. */
public class MainActivityAdapter extends FragmentPagerAdapter {

    private MapFragment mapFragment;
    private PreferencesFragment preferencesFragment;

    public MainActivityAdapter(FragmentManager fm) {
        super(fm);
        mapFragment = MapFragment.newInstance();
        preferencesFragment = new PreferencesFragment();
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return mapFragment;
            case 1:
                return preferencesFragment;
            default:
                return null;
        }
    }
}

【讨论】:

    【解决方案4】:

    根据 2019 年的 AndroidX

    implementation 'androidx.legacy:legacy-support-v13:1.0.0'
    implementation 'androidx.viewpager:viewpager:1.0.0'
    

    【讨论】:

      【解决方案5】:

      有同样的问题。我的解决方案是从android.support.v4.app.FragmentPagerAdapter 中复制代码,然后将导入的Fragment 类更改为android.app.Fragment。之后进行其他小的调整以消除所有错误。令我惊讶的是,它完美地工作。 IMO 这比添加您并不真正需要的支持库要简单。

      import android.app.Fragment;
      import android.app.FragmentManager;
      import android.app.FragmentTransaction;
      import android.os.Parcelable;
      import android.support.v4.view.PagerAdapter;
      import android.view.View;
      import android.view.ViewGroup;
      
      /**
       * PagerAdapter for ViewPager that is compatible with android.app.Fragment.
       */
      abstract class FragmentPagerAdapter extends PagerAdapter {
      
          private final FragmentManager mFragmentManager;
          private FragmentTransaction mCurTransaction = null;
          private Fragment mCurrentPrimaryItem = null;
      
          /**
           * Returns a unique id for the fragment on the given position.
           * For example this can be the view id that is used on the page's fragment.
           * @param position The page index
           * @return An id that is unique with respect to the pages in the adapter.
           */
          abstract long getItemId(int position);
      
          /**
           * Returns the fragment for the given page index.
           * @param position The page index
           * @return The fragment
           */
          abstract Fragment getItem(int position);
      
          public FragmentPagerAdapter(FragmentManager fragmentManager) {
              super();
              mFragmentManager = fragmentManager;
          }
      
          @Override
          public Object instantiateItem(ViewGroup container, int position) {
              if (mCurTransaction == null) {
                  mCurTransaction = mFragmentManager.beginTransaction();
              }
      
              final long itemId = getItemId(position);
      
              // Do we already have this fragment?
              String name = makeFragmentName(container.getId(), itemId);
              Fragment fragment = mFragmentManager.findFragmentByTag(name);
              if (fragment != null) {
                  mCurTransaction.attach(fragment);
              } else {
                  fragment = getItem(position);
                  mCurTransaction.add(container.getId(), fragment,
                          makeFragmentName(container.getId(), itemId));
              }
              if (fragment != mCurrentPrimaryItem) {
                  fragment.setMenuVisibility(false);
              }
      
              return fragment;
          }
      
          @Override
          public void destroyItem(ViewGroup container, int position, Object object) {
              if (mCurTransaction == null) {
                  mCurTransaction = mFragmentManager.beginTransaction();
              }
              mCurTransaction.detach((Fragment) object);
          }
      
          @SuppressWarnings("ReferenceEquality")
          @Override
          public void setPrimaryItem(ViewGroup container, int position, Object object) {
              Fragment fragment = (Fragment)object;
              if (fragment != mCurrentPrimaryItem) {
                  if (mCurrentPrimaryItem != null) {
                      mCurrentPrimaryItem.setMenuVisibility(false);
                  }
                  if (fragment != null) {
                      fragment.setMenuVisibility(true);
                  }
                  mCurrentPrimaryItem = fragment;
              }
          }
      
          @Override
          public void finishUpdate(ViewGroup container) {
              if (mCurTransaction != null) {
                  mCurTransaction.commitAllowingStateLoss();
                  mCurTransaction = null;
              }
          }
      
          @Override
          public boolean isViewFromObject(View view, Object object) {
              return ((Fragment)object).getView() == view;
          }
      
          @Override
          public Parcelable saveState() {
              return null;
          }
      
          @Override
          public void restoreState(Parcelable state, ClassLoader loader) {
          }
      
          private static String makeFragmentName(int viewId, long id) {
              return "android:switcher:" + viewId + ":" + id;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2013-07-07
        • 1970-01-01
        • 1970-01-01
        • 2018-11-10
        • 1970-01-01
        • 1970-01-01
        • 2017-03-15
        • 1970-01-01
        • 2014-08-24
        相关资源
        最近更新 更多