gpt4 book ai didi

android - 替换 ViewPager 中的 Fragment

转载 作者:IT老高 更新时间:2023-10-28 12:51:06 28 4
gpt4 key购买 nike

我正在尝试通过 FragmentPagerAdapter 将 Fragment 与 ViewPager 一起使用。我要实现的是将位于 ViewPager 第一页上的 fragment 替换为另一个 fragment 。

寻呼机由两个页面组成。第一个是FirstPagerFragment,第二个是SecondPagerFragment。单击第一页的按钮。我想用 NextFragment 替换 FirstPagerFragment

下面是我的代码。

public class FragmentPagerActivity extends FragmentActivity {

static final int NUM_ITEMS = 2;

MyAdapter mAdapter;
ViewPager mPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pager);

mAdapter = new MyAdapter(getSupportFragmentManager());

mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);

}


/**
* Pager Adapter
*/
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}

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

@Override
public Fragment getItem(int position) {

if(position == 0) {
return FirstPageFragment.newInstance();
} else {
return SecondPageFragment.newInstance();
}

}
}


/**
* Second Page FRAGMENT
*/
public static class SecondPageFragment extends Fragment {

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Log.d("DEBUG", "onCreateView");
return inflater.inflate(R.layout.second, container, false);

}
}

/**
* FIRST PAGE FRAGMENT
*/
public static class FirstPageFragment extends Fragment {

Button button;

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Log.d("DEBUG", "onCreateView");
View root = inflater.inflate(R.layout.first, container, false);
button = (Button) root.findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.replace(R.id.first_fragment_root_id, NextFragment.newInstance());
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
trans.addToBackStack(null);
trans.commit();

}

});

return root;
}

/**
* Next Page FRAGMENT in the First Page
*/
public static class NextFragment extends Fragment {

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Log.d("DEBUG", "onCreateView");
return inflater.inflate(R.layout.next, container, false);

}
}
}

...这里是 xml 文件

fragment_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:padding="4dip"
android:gravity="center_horizontal"
android:layout_width="match_parent" android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</android.support.v4.view.ViewPager>

</LinearLayout>

first.xml

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

<Button android:id="@+id/button"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="to next"/>

</LinearLayout>

现在的问题...我应该使用哪个 ID

trans.replace(R.id.first_fragment_root_id, NextFragment.newInstance());

?

如果我使用 R.id.first_fragment_root_id,替换是有效的,但是 Hierarchy Viewer 显示了一个奇怪的行为,如下所示。

一开始的情况是

更换后的情况是

如您所见,有问题,我希望在替换 fragment 后找到与第一张图片相同的状态。

最佳答案

还有一种方案,不需要修改ViewPagerFragmentStatePagerAdapter的源代码,与FragmentPagerAdapter基类配合使用作者。

我想首先回答作者关于他应该使用哪个 ID 的问题;它是容器的 ID,即 View 寻呼机本身的 ID。但是,您可能已经注意到,在您的代码中使用该 ID 不会导致任何事情发生。我会解释原因:

首先,要使 ViewPager 重新填充页面,您需要调用位于适配器基类中的 notifyDataSetChanged()

其次,ViewPager使用getItemPosition()抽象方法来检查哪些页面应该被销毁,哪些应该被保留。此函数的默认实现总是返回 POSITION_UNCHANGED,这会导致 ViewPager 保留所有当前页面,因此不会附加您的新页面。因此,要进行 fragment 替换,getItemPosition() 需要在您的适配器中被覆盖,并且在使用旧的、要隐藏的 fragment 作为参数调用时必须返回 POSITION_NONE

这也意味着您的适配器总是需要知道哪个 fragment 应该显示在位置 0,FirstPageFragmentNextFragment。一种方法是在创建 FirstPageFragment 时提供一个监听器,该监听器将在需要切换 fragment 时调用。我认为这是一件好事,让您的 fragment 适配器处理所有 fragment 切换和对 ViewPagerFragmentManager 的调用。

第三,FragmentPagerAdapter通过一个派生自位置的名称缓存使用的 fragment ,因此如果位置0有 fragment ,即使类是新的也不会被替换。有两种解决方案,最简单的方法是使用FragmentTransactionremove()函数,它也会删除它的标签。

那是很多文字,这里的代码应该适用于你的情况:

public class MyAdapter extends FragmentPagerAdapter
{
static final int NUM_ITEMS = 2;
private final FragmentManager mFragmentManager;
private Fragment mFragmentAtPos0;

public MyAdapter(FragmentManager fm)
{
super(fm);
mFragmentManager = fm;
}

@Override
public Fragment getItem(int position)
{
if (position == 0)
{
if (mFragmentAtPos0 == null)
{
mFragmentAtPos0 = FirstPageFragment.newInstance(new FirstPageFragmentListener()
{
public void onSwitchToNextFragment()
{
mFragmentManager.beginTransaction().remove(mFragmentAtPos0).commit();
mFragmentAtPos0 = NextFragment.newInstance();
notifyDataSetChanged();
}
});
}
return mFragmentAtPos0;
}
else
return SecondPageFragment.newInstance();
}

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

@Override
public int getItemPosition(Object object)
{
if (object instanceof FirstPageFragment && mFragmentAtPos0 instanceof NextFragment)
return POSITION_NONE;
return POSITION_UNCHANGED;
}
}

public interface FirstPageFragmentListener
{
void onSwitchToNextFragment();
}

希望这对任何人都有帮助!

关于android - 替换 ViewPager 中的 Fragment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7723964/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com