【问题标题】:How to use ActionBar, ViewPager and Fragments and correctly replace fragments inside pages如何使用 ActionBar、ViewPager 和 Fragments 并正确替换页面内的 Fragment
【发布时间】:2023-03-25 08:56:01
【问题描述】:

我还是 Android 开发新手,我正在尝试开发一个带有 actionBar 选项卡、滑动效果和片段的应用程序。但是在过去的 3 天里,我没有解决在 viewPager 中替换片段的问题。我已经尝试了在几个互联网页面上找到的很多想法,但没有任何帮助我解决这个问题。没有我的代码被浪费了,因为我已经删除了它并开始了新的替换。 但我想这次我需要完全了解片段(状态)PagerAdapter 的行为,然后再实现它。 所以我现在有几个问题。

1. 是否可以使用 actionbar 和 viewPager 以及另外使用可以在页面上替换为另一个页面的片段?
2.是否可以保存这些替换的状态并切换到另一个寻呼机与替换相同的片段页面进行交互,然后返回上一页恢复页面?
3.我需要什么来实现这种行为?我真的需要重写哪些方法?我需要如何覆盖它们?
4. 是否可以用于同一片段的所有页面实例?我需要一些东西来区分它们吗?那么我可以使用这个片段,从同一个类实例化,同样的 xml 布局文件吗? viewPager 是否知道当前要替换哪个页面的哪个布局上的哪个资源?
5. 为什么只有教程只解释actionbar,或者只解释ViewPagerAdapter的swipe,而另外解释如何在viewpager和actionbar中实现fragment替换。简单地结合这些教程?

所以我原谅我心情不好的写作,但我仍然被这个该死的问题所困扰。请原谅我的英语不好,我不是母语人士,我只是使用我在学校的旧英语知识。 如果有人可以帮助我,或者给我一个例子,我会非常高兴。

请帮忙,贾斯图斯

编辑于 2014 年 3 月 30 日 这是我目前使用的来源。

MainActivity.java:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private ActionBar actionBar;
private Menue[] menuesDto;
private MyViewPagerAdapter myViewPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bundle extras = getIntent().getExtras();
    String jsonString = extras.getString("jsonString");
    Gson g = new Gson();
    Type type = new TypeToken<Menue[]>() {
    }.getType();
    this.menuesDto = g.fromJson(jsonString, type);

    createTabBar();
}

@Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
    // Log.d("MyZooApp2", "onTabSelected at position " + tab.getPosition() +
    // " name " + tab.getTag());
    tab.setIcon(this.menuesDto[tab.getPosition()].getSelectedIcon());
    viewPager.setCurrentItem(tab.getPosition(), true);
}

@Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
    // Log.d("MyZooApp2", "onTabUnselected at position " + tab.getPosition()
    // + " name " + tab.getText());
    tab.setIcon(this.menuesDto[tab.getPosition()].getUnselectedIcon());
}

private void createTabBar() {
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    setContentView(R.layout.activity_main);
    viewPager = (ViewPager) findViewById(R.id.pager);
    for (int i = 0; i < menuesDto.length; i++) {
        Menue menue = menuesDto[i];
        FragmentBuilder.setTabIconForChangeState(menue);
        String name = menue.getName();
        ActionBar.Tab tab = actionBar.newTab();
        tab.setText(name);
        tab.setIcon(menue.getUnselectedIcon());
        actionBar.addTab(tab);
    }

    myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager(), this);
    viewPager.setAdapter(myViewPagerAdapter);
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int arg0) {
            // Log.d("MyZooApp2", "onPageSelected at position " + arg0);
            actionBar.setSelectedNavigationItem(arg0);
        }
    });
}

public MyViewPagerAdapter getMyViewPagerAdapter() {
    return myViewPagerAdapter;
}
}

菜单片段.java:

public class MenueFragment extends Fragment implements ZooFragment, ResourceCaller {
private Menue menue;
private ListView listView;
private String[] navList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.menue_fragment, container, false);
    init();
    if (menue.getNavs().size() > 0) {
        listView = (ListView) v.findViewById(R.id.list);
        new FileResourceLoader(menue, getActivity(), this).execute();
    } else {
        // createContentComponents();
    }
    return v;
}

public static MenueFragment newInstance() {
    MenueFragment f = new MenueFragment();
    return f;
}

@Override
public void init() {
    String jsonString = getArguments().getString("childNodes");
    Gson gson = new Gson();
    this.menue = gson.fromJson(jsonString, Menue.class);
    navList = new String[menue.getNavs().size()];
}

private void createNavigationComponents(List<Nav> navs) {
    listView.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.list_item, navList));
    listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            FragmentTransaction trans = getActivity().getSupportFragmentManager().beginTransaction();
            trans.replace(R.id.nav_here, new EmptyFragment());
            trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            trans.addToBackStack(null);
            trans.commit();
            ((MainActivity) getActivity()).getMyViewPagerAdapter().notifyDataSetChanged();
        }
    });
}
}

MyViewPAgerAdapter.java:

public class MyViewPagerAdapter extends FragmentStatePagerAdapter {

public static final int FRAGMENT1 = 0;
public static final int FRAGMENT2 = 1;
public static final int FRAGMENT3 = 2;
public static final int FRAGMENT4 = 3;
public static final int FRAGMENT5 = 4;

private final MainActivity mainActivity;
private ZooFragment[] fragments;

public MyViewPagerAdapter(FragmentManager fm, MainActivity mainActivity) {
    super(fm);
    this.mainActivity = mainActivity;
    fragments = new ZooFragment[mainActivity.getTabCount()];
}

@Override
public Fragment getItem(int position) {
    Menue menue = mainActivity.getMenuesDtoAtPos(position);
    switch (position) {
    case FRAGMENT1:
        if (fragments[FRAGMENT1] == null) {
            fragments[FRAGMENT1] = FragmentBuilder.getMenueFragment(mainActivity, menue);
        }
        break;
    case FRAGMENT2:
        if (fragments[FRAGMENT2] == null) {
            fragments[FRAGMENT2] = FragmentBuilder.getMenueFragment(mainActivity, menue);

        }
        break;
    case FRAGMENT3:
        if (fragments[FRAGMENT3] == null) {
            fragments[FRAGMENT3] = FragmentBuilder.getMenueFragment(mainActivity, menue);

        }
        break;
    case FRAGMENT4:
        if (fragments[FRAGMENT4] == null) {
            fragments[FRAGMENT4] = FragmentBuilder.getMenueFragment(mainActivity, menue);

        }
        break;
    case FRAGMENT5:
        if (fragments[FRAGMENT5] == null) {
            fragments[FRAGMENT5] = FragmentBuilder.getMenueFragment(mainActivity, menue);

        }
        break;
    }

    Log.d("MyZooApp2", "getItem: for Position: " + position + " added: " + menue.getName());

    return (Fragment) fragments[position];

}

@Override
public int getCount() {
    return fragments.length;
}
}

还有两个 layouts.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_here"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:cacheColorHint="#DDEE22"
    android:divider="#55FFAA"
    android:scrollbarStyle="outsideOverlay" />

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#AA33EE"
android:orientation="vertical" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

我希望有人对 TisSarah 的评论中描述的我的问题有另一种解决方案。

2014 年 3 月 31 日编辑: 如果像您推荐的那样更改了我的 Tab 和 viewpager 侦听器的侦听器实现,并添加了一些 LogCat 输出。

VIA SWIPE:
03-31 19:10:05.914: D/MyZooApp2(5674): onTabUnselected at position 0 name Home
03-31 19:10:05.914: D/MyZooApp2(5674): onTabSelected at position 1 name null
03-31 19:10:05.924: D/MyZooApp2(5674): onPageSelected at position 1
03-31 19:10:06.895: D/MyZooApp2(5674): getItem: for Position: 2 added: Tiere
03-31 19:10:08.396: D/MyZooApp2(5674): onTabUnselected at position 1 name Zookarte
03-31 19:10:08.406: D/MyZooApp2(5674): onTabSelected at position 2 name null
03-31 19:10:08.406: D/MyZooApp2(5674): onPageSelected at position 2
03-31 19:10:09.187: D/MyZooApp2(5674): getItem: for Position: 3 added: Fütterung

VIA TAB SELECTION:
03-31 19:11:06.353: D/MyZooApp2(5674): onTabUnselected at position 2 name Tiere
03-31 19:11:06.353: D/MyZooApp2(5674): onTabSelected at position 0 name null
03-31 19:11:06.353: D/MyZooApp2(5674): getItem: for Position: 0 added: Home
03-31 19:11:06.984: D/MyZooApp2(5674): onTabReselected at position 0 name Home
03-31 19:11:06.984: D/MyZooApp2(5674): onPageSelected at position 0
03-31 19:11:11.488: D/MyZooApp2(5674): onTabUnselected at position 0 name Home
03-31 19:11:11.488: D/MyZooApp2(5674): onTabSelected at position 2 name null
03-31 19:11:11.498: D/MyZooApp2(5674): getItem: for Position: 2 added: Tiere
03-31 19:11:11.498: D/MyZooApp2(5674): getItem: for Position: 3 added: Fütterung

SWIPE + TAB SELECTION AND LISTITEM CLICKS:
03-31 19:18:27.123: D/MyZooApp2(9138): ListItem 0 on page Home clicked //After load item clicked -> Fragment replacement correct
03-31 19:18:38.094: D/MyZooApp2(9138): onTabUnselected at position 0 name Home
03-31 19:18:38.094: D/MyZooApp2(9138): onTabSelected at position 2 name null
03-31 19:18:38.134: D/MyZooApp2(9138): getItem: for Position: 2 added: Tiere //swiping to page 2 and click -> Fragment replacement incorrect. It´s replaced on page 1
03-31 19:18:38.154: D/MyZooApp2(9138): getItem: for Position: 3 added: Fütterung    //same page (2) and click -> Fragment replacement incorrect. It´s replaced on page 1
03-31 19:18:38.344: D/MyZooApp2(9138): onTabReselected at position 2 name Tiere
03-31 19:18:38.344: D/MyZooApp2(9138): onPageSelected at position 2
03-31 19:18:39.615: D/MyZooApp2(9138): ListItem 0 on page Tiere clicked  //swiping to page 0 and click -> Fragment replacement incorrect.It´s replaced on page 1
03-31 19:18:41.107: D/MyZooApp2(9138): onTabUnselected at position 2 name Tiere
03-31 19:18:41.107: D/MyZooApp2(9138): onTabSelected at position 1 name null
03-31 19:18:41.117: D/MyZooApp2(9138): onPageSelected at position 1
03-31 19:20:05.089: D/MyZooApp2(9138): onTabUnselected at position 1 name Zookarte
03-31 19:20:05.089: D/MyZooApp2(9138): onTabSelected at position 2 name null
03-31 19:20:05.089: D/MyZooApp2(9138): onPageSelected at position 2
03-31 19:20:06.550: D/MyZooApp2(9138): onTabUnselected at position 2 name Tiere
03-31 19:20:06.550: D/MyZooApp2(9138): onTabSelected at position 3 name null
03-31 19:20:06.560: D/MyZooApp2(9138): onPageSelected at position 3
03-31 19:20:07.020: D/MyZooApp2(9138): getItem: for Position: 4 added: Mehr
03-31 19:20:07.911: D/MyZooApp2(9138): onTabUnselected at position 3 name Fütterung
03-31 19:20:07.911: D/MyZooApp2(9138): onTabSelected at position 4 name null
03-31 19:20:07.921: D/MyZooApp2(9138): onPageSelected at position 4
03-31 19:20:09.763: D/MyZooApp2(9138): onTabUnselected at position 4 name Mehr
03-31 19:20:09.763: D/MyZooApp2(9138): onTabSelected at position 2 name null
03-31 19:20:09.853: D/MyZooApp2(9138): onTabReselected at position 2 name Tiere
03-31 19:20:09.853: D/MyZooApp2(9138): onPageSelected at position 2
03-31 19:20:11.074: D/MyZooApp2(9138): ListItem 0 on page Tiere clicked //a few swipes and tab selections done and back on page 0 and click -> Fragment replacement incorrect. It´s replaced on page 1
03-31 19:20:12.426: D/MyZooApp2(9138): onTabUnselected at position 2 name Tiere
03-31 19:20:12.436: D/MyZooApp2(9138): onTabSelected at position 1 name null
03-31 19:20:12.436: D/MyZooApp2(9138): onPageSelected at position 1
03-31 19:20:13.397: D/MyZooApp2(9138): onTabUnselected at position 1 name Zookarte
03-31 19:20:13.407: D/MyZooApp2(9138): onTabSelected at position 0 name null
03-31 19:20:13.407: D/MyZooApp2(9138): onPageSelected at position 0
03-31 19:20:14.878: D/MyZooApp2(9138): ListItem 0 on page Home clicked //only tab         selections back on page 0 and click -> Fragment replacement incorrect. It´s             replaced on page 1

Fragment setup:
page 0 -> Fragment1 (Home) layout: frag1.xml contains programmatically added listitems from a json response
page 1 -> Fragment1 (Zookarte) layout: frag1.xml contains only an imageview
page 2 -> Fragment1 (Tiere) layout: frag1.xml contains programmatically added listitems from a json response
page 3 -> Fragment1 (Fütterung) layout: frag1.xml contains only an imageview
page 4 -> Fragment1 (Mehr) layout: frag1.xml contains only an imageview

【问题讨论】:

    标签: android-fragments android-actionbar android-viewpager fragmentpageradapter


    【解决方案1】:

    首先,我认为这个链接可能对你很有帮助:http://developer.android.com/training/implementing-navigation/lateral.html

    1. 是的。 https://github.com/thecodepath/android_guides/wiki/ViewPager-with-FragmentPagerAdapter
    2. 是的。您将像往常一样使用 savedInstanceSTate 保存片段状态
    3. 查看以上链接,将其连接到操作栏标签栏 你需要创建一个 TabListener
    4. 是的,只需让您的 FragmentPagerAdapter 创建相同片段的实例,这 如果你在你的 onCreateView 方法。视图寻呼机将处理跟踪 哪个实例在哪个页面上(你会的,在 viewpager 中)。
    5. 您需要在视图寻呼机中保留一个片段列表,以便 您可以在 getItem 方法中返回适当的(我 通常使用 switch 语句和一些常量来跟踪 为哪个视图寻呼机位置返回哪些片段)。

    这有点令人沮丧,但你会得到它的窍门!

    这是一个例子

    public class MyPagerAdapter extends FragmentPagerAdapter {
        public static final int FRAGMENT1 = 0;
        public static final int FRAGMENT2 = 1;
    
        private Fragment[] fragments;
    
        public MyPagerAdapter(Activity activity, FragmentManager fragmentManager) {
            super(fragmentManager);
           fragments = new Fragment[2];
        }
    
        @Override
        public Fragment getItem(int i) {
            switch(i){
                case FRAGMENT1:
                    if(fragment[FRAGMENT1] == null) {
                         fragment[FRAGMENT1] = new FragmentOne.createInstance();
                    }
                    break;
                case FRAGMENT2:
                    if(fragment[FRAGMENT2] == null) {
                         fragment[FRAGMENT2] = new FragmentTWO.createInstance();
                    }
                    break;
            }
            return fragments[i];
        }
    
        @Override
        public int getCount() {
            return fragments.length;
        }
    }
    

    您需要覆盖活动类中的侦听器:

    private ViewPager.OnPageChangeListener mPagerChangeListener
            = new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(0);
    
            ActionBar actionBar = getActionBar();
            actionBar.selectTab(actionBar.getTabAt(position));
        }
    };
    
    private ActionBar.TabListener mTabListener = new ActionBar.TabListener() {
        @Override
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
            mViewPager.setCurrentItem(tab.getPosition());
        }
    
        @Override
        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        }
    
        @Override
        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        }
    };
    

    【讨论】:

    • 感谢 Sarah 的帮助,但不幸的是它并没有解决我的问题。我已经为 getItem() 尝试了类似的实现。滑动和选项卡选择似乎正确执行。但是标签/页面上的片段替换不正确。有时,当前 -1 或当前 +1 的片段会被替换。我不知道为什么。是否绝对有必要在我的 PagerAdapter 中覆盖 getItemPosition()?如果是这样,我应该如何覆盖它?如果我为全班发布我的代码,也许会有所帮助?
    • 我已经扩展了您的解决方案。现在我从 FragmentStatePagerAdapter 扩展并在 ft.replace() 之后调用 notifyDataSetChanged()。但我没有改变任何东西。 :-(
    • 我已经添加了我的来源。
    • 我添加了一些你想用至少显示的内容实现的监听器。
    • 我添加了你的监听器实现的输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 2013-09-15
    • 1970-01-01
    • 2017-04-07
    • 2011-12-05
    • 1970-01-01
    相关资源
    最近更新 更多