我想要的是什么。
在选项卡滑动菜单上下文中,我想在选项卡内将片段替换为另一个片段,并维护选项卡菜单以及当前选项卡。当滑动到另一个选项卡并返回原始时,我希望显示最后一个片段。
例如,我tab_a
Fragment_1
,tab_b
Fragment_4
和tab_c
Fragment_7
。现在我想要Fragment_1
中的一个按钮打开我Fragment_2
,但我希望能够滑动到tab_b
和tab_c
的片段。当我返回tab_a时,必须显示Fragment_2
。
MainActivity
|
|
ContainerFragment
|
|
|_ _ _ Tab A
| |_ _ _ Fragment 1
| |
| |_ _ _ Fragment 2
| |
| |_ _ _ Fragment 3
| |
| |_ _ _ ...
|
|_ _ _ Tab B
| |_ _ _ Fragment 4
| |
| |_ _ _ Fragment 5
| |
| |_ _ _ Fragment 6
| |
| |_ _ _ ...
|
|_ _ _ Tab C
| |_ _ _ Fragment 7
| |
| |_ _ _ Fragment 8
| |
| |_ _ _ Fragment 8
| |
| |_ _ _ ...
我目前的主要活动。
XML
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
代码
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private final static int[] tabIcons = {
R.drawable.ic_tab_a,
R.drawable.ic_tab_b,
R.drawable.ic_tab_c
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new Fragment1());
adapter.addFrag(new Fragment4());
adapter.addFrag(new Fragment7());
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
void addFrag(Fragment fragment) {
mFragmentList.add(fragment);
}
}
}
片段
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/holo_blue_light"
android:id="@+id/fragment_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="myContext">
<Button
android:text="Go to next Fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:id="@+id/button_nextFrag" />
<FrameLayout
android:id="@+id/tab1_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
代码
public class Fragment1 extends Fragment {
private void goNextFragment() {
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.replace(R.id.tab1_container, new Fragment2());
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
trans.addToBackStack(null);
trans.commit();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment.
View root = inflater.inflate(R.layout.fragment_1, container, false);
// Go to next Fragment Button.
final Button nextFrag = (Button) root.findViewById(R.id.button_nextFrag);
nextFrag .setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goNextFragment();
}
});
return root;
}
}
编辑:
我有一些解决方案,但没有一个是完美的。如果我在MainActivity中放置了Framelayaout,Fragment_1
已正确替换为Fragment_2
,但它也位于tab_b
和tab_c
中。如果FrameLayout位于Fragment_1
,我可以正确滑动其他标签,但替换效果不佳,因为Fragment_2
已打开,但Fragment_1
也在那里。
答案 0 :(得分:3)
根据您的解释,我实施了以下内容:
1-在您的活动中创建Tabs
和ViewPager
:
mPager = (ViewPager) findViewById(R.id.vp_pager);
mPager.setOffscreenPageLimit(3);
PagerAdapter mAdapter = new PagerAdapter(getSupportFragmentManager(), getContext());
mPager.setAdapter(mAdapter);
//tab.setupWithViewPager(mPager);
2-在每个标签中创建ViewPager
(我假设您需要tabs
内的标签,如果您不需要标签只是删除它们),每个fragment
的实现将类似于:
ViewPager mPager = (ViewPager) rootView.findViewById(R.id.vp_pager);
mPager.setOffscreenPageLimit(3);
CategoryAdapter mAdapter = new CategoryAdapter(getChildFragmentManager());//make sure this ChildFragmentManager
mPager.setAdapter(mAdapter);
同样在片段中创建一个Button,当Click转到另一个片段时:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mPager.setCurrentItem(1); // go to second fragment
}
});
最终结果将类似于以下内容,如果您转到主页标签然后返回类别标签,那么您的Fragment
位置不是改变。
你应该记住两点:
mPager.setOffscreenPageLimit(3);
getChildFragmentManager()
而不是FragmentManager()
如果你不需要Inner ViewPager
而你只想在这里加载一个Fragment实例,这是另一种选择:
1-完成上一个方式的第一项。
2-在你的片段中,xml放入FrameContainer并将片段加载到其中:
CategoryResultFragment f = CategoryResultFragment.newInstance();
getFragmentManager().beginTransaction()
.replace(R.id.frame_result_container, f)
.commit();
修改:这不是最佳方法,但我认为可以解决您的问题:
1-在MainActivity
中创建一个静态字段,如下所示:
static String[] type = new String[3];
2-当您在片段中调用onClick时,请更新String
中的MainActivity
值。
public static update currentType(int pos,String type);
第一个值是ViewPager位置,第二个值是你的内部Fragment类型(例如:fragment_d);
3-在您的ViewPager中
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: // first tab
if(type[position] == "fragment_d")
return new Fragment_D();
else
return new Fragment_B();
}
}
答案 1 :(得分:2)
您可以将ViewPager
与TabLayout
一起使用。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
然后创建一个扩展FragmentStatePagerAdapter
的类,用初始ViewPager
初始化Fragment
:
public class CustomPagerAdapter extends FragmentStatePagerAdapter {
private final List<String> tabTitles = new ArrayList<String>() {{
add("Fragment 1");
add("Fragment 4");
add("Fragment 7");
}};
private List<Fragment> tabs = new ArrayList<>();
public CustomPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
initializeTabs();
}
private void initializeTabs() {
tabs.add(HostFragment.newInstance(new Fragment1()));
tabs.add(HostFragment.newInstance(new Fragment4()));
tabs.add(HostFragment.newInstance(new Fragment7()));
}
@Override
public Fragment getItem(int position) {
return tabs.get(position);
}
@Override
public int getCount() {
return tabs.size();
}
@Override
public CharSequence getPageTitle(int position) {
return tabTitles.get(position);
}
}
包含实际内容的片段应该用HostFragment
包裹,如果你想导航,或者弹出最后一个片段,它会使用它的子FragmentManager
用新的片段替换当前片段来自片段堆栈。调用其replaceFragment
进行导航:
public class HostFragment extends BackStackFragment {
private Fragment fragment;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.host_fragment, container, false);
if (fragment != null) {
replaceFragment(fragment, false);
}
return view;
}
public void replaceFragment(Fragment fragment, boolean addToBackstack) {
if (addToBackstack) {
getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit();
} else {
getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit();
}
}
public static HostFragment newInstance(Fragment fragment) {
HostFragment hostFragment = new HostFragment();
hostFragment.fragment = fragment;
return hostFragment;
}
}
HostFragment应扩展抽象类BackstackFragment
public abstract class BackStackFragment extends Fragment {
public static boolean handleBackPressed(FragmentManager fm)
{
if(fm.getFragments() != null){
for(Fragment frag : fm.getFragments()){
if(frag != null && frag.isVisible() && frag instanceof BackStackFragment){
if(((BackStackFragment)frag).onBackPressed()){
return true;
}
}
}
}
return false;
}
protected boolean onBackPressed()
{
FragmentManager fm = getChildFragmentManager();
if(handleBackPressed(fm)){
return true;
} else if(getUserVisibleHint() && fm.getBackStackEntryCount() > 0){
fm.popBackStack();
return true;
}
return false;
}
}
在MainActivity
:
public class MainActivity extends AppCompatActivity {
private CustomPagerAdapter customPagerAdapter;
private ViewPager viewPager;
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
customPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager());
// 2 is enough for us; increase if you have more tabs!
viewPager.setOffscreenPageLimit(2);
viewPager.setAdapter(customPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onBackPressed()
{
if(!BackStackFragment.handleBackPressed(getSupportFragmentManager())){
super.onBackPressed();
}
}
public void openNextFragment() {
HostFragment hostFragment = (HostFragment) customPagerAdapter.getItem(viewPager.getCurrentItem());
// your logic to change the fragments...
}
}
这个解决方案肯定不是完美的,但可以完成工作。关于这个问题,请在blog post中了解更多关于它的问题。
答案 2 :(得分:0)
您可以更改页面片段内的片段。例如,TAB_A实现拾取片段1或2的逻辑,并在内部显示拾取的片段。 层次结构如下:
ViewPager - &gt; TAB_A - &gt;片段1或2(在TAB_A中显示)。
此外,您应该使用getChildFragmentManager()来管理TAB_A中的片段。