Android-片段和分页通讯

时间:2018-12-20 08:06:56

标签: android android-fragments android-viewpager android-tablayout

我刚接触Android。

这是我的情况:我有一个带有3个标签的简单应用。在每个标签中,我要使用一个或多个片段。这是这种情况:

  1. 标签1:
    • 片段A
  2. 选项卡2:
    • 片段B
    • 片段C
    • D片段
  3. 选项卡3:
    • 片段E
    • 片段F

在“选项卡1”中,我没有问题。一切都很好。当我需要移动“制表2”和“制表3”时会出现问题。

在选项卡2中,我必须将一些参数从“片段B”传播到“片段C”,并从“片段C”传播到“片段D”。

然后可能发生,当用户单击“片段D”中的某个按钮时,我必须传递到“标签3”,并且必须将某些参数从“片段D”传播到“片段E”。

在用于标签处理的主要活动中,我正在使用以下组件:

  • android.support.design.widget.TabLayout
  • android.support.v4.view.ViewPager
  • android.support.v4.app.FragmentStatePagerAdapter(我创建了一个自定义 类)
  • android.support.design.widget.TabLayout.OnTabSelectedListener(我创建了一个自定义类)

我非常简单的FragmentStatePagerAdapter扩展名是:

public class MyOwnPageAdapter extends FragmentStatePagerAdapter {
    private int numeroTab;
    public MyOwnPageAdapter(FragmentManager fm, int numeroTab) {
        super(fm);
        this.numeroTab = numeroTab;
    }
    @Override
    public Fragment getItem(int position) {
        switch (position){
            case 0:
                return new FragmentA() ;
            case 1:
                return new FragmentB() ;
            case 2:
                return new FragmentC() ;
            default:
                return null;
        }
    }
    @Override
    public int getCount() {
        return numeroTab;
    }
}

我非常简单的TabLayout.OnTabSelectedListener扩展名是:

public class TabSelectedListener implements TabLayout.OnTabSelectedListener {
    private ViewPager viewPager;
    public TabSelectedListener(ViewPager viewPager){

        this.viewPager = viewPager;
    }
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        viewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {

    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {

    }
}

我能够在选项卡2中的选项卡内切换片段,我可以从片段B切换到片段C,依此类推。我在片段之间传递参数时遇到问题,尤其是从选项卡2中的片段D到选项卡3中的片段E

在使用android.support.v4.app.FragmentManager的片段实现中,我可以通过执行以下操作来添加和删除视图(例如片段):

mFragmentManager.beginTransaction().add(rootView.getId(),mListaEdificiFragment, "BUILDS").addToBackStack(null).commit();

问题在于参数传播,因为FragmentStatePagerAdapter似乎在缓存视图,所以发生了片段构造函数被调用,而onCreateonCreateView不再被调用的情况,所以我可以t处理传播的参数。

对此有什么解决办法吗?还是我的导航模式完全错误?我想避免在一个“大视图”中将片段B,片段C和片段D折叠起来,以隐藏某些部分(片段E和片段F相同)

欢迎任何建议

天使

4 个答案:

答案 0 :(得分:0)

将变量值从一个片段转移到另一个片段的一种简单解决方案是共享首选项(也可以用于将值从一个活动转移到另一个活动)。共享的首选项将针对变量保存数据,这些变量将在Android应用程序的所有活动和片段中持续存在。

现在,就您的情况而言,假设您要将值name = angelo从片段A传输到片段B。在片段A中,编写以下代码:

 Button updateName = findViewById(R.id.btnupdateTeamName);
 updateTeamName .setOnClickListener(new View.OnClickListener() {
 @Override
    public void onClick(View v) {
        SharedPreferences.Editor editor = sharedpreferences.edit();
        editor.putString("name", "angelo");
        editor.commit();
    }
 });

执行后,以上代码将在共享首选项中使用name更新值angelo。这将在您的整个应用中都可用。

有关共享首选项的更多信息,请查看此官方document

答案 1 :(得分:0)

我这样写Fragment是为了将数据传递给它。

public class MyFragment extends Fragment {
    private static String ARG_PARAM1 = "data";
    private String data;

    public MyFragment() {
        // Required empty public constructor
    }

    public static MyFragment newInstance(String data) {
        MyFragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, data);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            data = getArguments().getString(ARG_PARAM1);
        }
    }
}

现在可以通过调用Fragment将数据传递到MyFragment.newInstance("Hello")。我希望这会有所帮助。

答案 2 :(得分:0)

我在项目中遇到了类似的问题。 就我而言,我有viewpager,每个标签都有多个片段。

因此,一种简单的解决方案是使用 LiveData ViewModel

在您的Tab2中:

  

片段B

     

片段C

     

D片段

     

TabTwoViewModel(包含实时数据)

在可变实时数据观察器中,此实时数据将存储到片段B,C和D。

更新实时数据对象时,实时数据会自动通知所有片段。

答案 3 :(得分:0)

最后我找到了解决方案。 由于主要问题是片段通信,因此我遵循了official documentation

假设我有片段A和文章列表,而片段B在我写的片段A中可以看到所选文章的详细信息:

public class FragmentA extends Fragment {
    private OnArticleSelectionListener mCallback;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
        }
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.activityedifici, container, false);     
        return rootView;
    }



    public interface OnArticleSelectionListener {

        void onArticleSelection(String articleId);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallback = null;
    }


    public void setOnArticleSelectionListener(OnArticleSelectionListener mCallback) {
        this.mCallback = mCallback;
    }
}

如您所见,我声明了以下接口

public interface OnArticleSelectionListener {

        void onArticleSelection(String articleId);
    }

这是文章选择侦听器。

在主要活动中,我写了以下内容:

public class MainActivity implements FragmentA.OnArticleSelectionListener{
//All my own stuffs

    @Override
    public void onAttachFragment(Fragment fragment) {
        if (fragment instanceof FragmentA){
            FragmentA ef = (FragmentA)fragment;
            ef.setOnArticleSelectionListener(this);
        }
    }
    @Override
    public void onArticleSelection(String articleId) {
        if( getSupportFragmentManager().findFragmentByTag(TAG_ARTICLE_DETAIL) != null ){
        //FragmentB is the article detail and it has already been created and cached
            FragmentB dcf = (FragmentB)getSupportFragmentManager().findFragmentByTag(TAG_ARTICLE_DETAIL);
            dcf.updateArticleDetail( articleId );
        }else{
        //FragmentB is the article detail and it has never been created I create and replace the container with this new fragment
            FragmentB dcf = new FragmentB();
        //Parameter propagation
            Bundle args = new Bundle();
            args.putString(FragmentB.ARG_ARTICLE_ID, articleId);
            dcf.setArguments(args);
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container_articles, dcf, TAG_ARTICLE_DETAIL);
            transaction.addToBackStack(null);
            transaction.commit();
        }
    }
}

通过这种方式,我可以拦截FragmentA中的事件,并将其传播到FragmentB;当我需要打开选项卡时,所有选项都保持不变,最后(在transaction.commit()dcf.updateArticleDetail( articleId )之后),我执行以下tabLayout.getTabAt(2).select();,然后打开第三个选项卡(选项卡索引从0开始)并显示“详细信息”。

我希望这会有用

天使