Converting ActivityGroup app to use Fragments/FragmentGroup

风流意气都作罢 提交于 2019-12-04 11:37:39

First you need to add Design Support Library and AppCompatLibrary into your Project

Add this code into your app gradle

compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'

layout for activity_main.xml (like main.xml in your code)

<?xml version="1.0" encoding="utf-8"?> 
<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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay">

    </android.support.v7.widget.Toolbar>

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

In above layout ViewPager will provides horizontal layout to display tabs. You can display more screens in a single screen using tabs. You can swipe the tabs quickly as you can.

Root Fragment

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

View for First Fragment

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#ff0"
android:layout_height="match_parent" >

<TextView
    android:id="@+id/tv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:text="@string/first_fragment" />
<Button 
    android:id="@+id/btn"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:layout_width="wrap_content"
    android:text="@string/to_second_fragment"/>

 </RelativeLayout>

View for Second and Individual(s) Fragment.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin">

<TextView
    android:id="@+id/section_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

</RelativeLayout>

Now add a MainActivity(like Main Activity in yours code) under which all this thing will handle.

public class MainActivity extends AppCompatActivity {

private TabGroupAdapter mTabGroupAdapter;
private ViewPager mViewPager;

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

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ArrayList<Fragment> fragmentList = new ArrayList<Fragment>();
    fragmentList.add(new RootFragment());
    fragmentList.add(new IndividualFragment1());
    fragmentList.add(new IndividualFragment2());
     ArrayList<String> name = new ArrayList<String>() {
        {
            add("Root Tab");
            add("Second Tab");
            add("Third Tab");
        }
    };
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mTabGroupAdapter = new TabGroupAdapter(getSupportFragmentManager(),name, fragmentList,);

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mTabGroupAdapter);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);

}
}

There is one FragmentPagerAdapter defined as mTabGroupAdapter inside MainActivity that will add a different tabs inside a single Layout.

First we bind the mTabGroupAdapter to mViewPager.

TabLayout will act like a TabHost under which Tab will be added by FragmentPagerAdapter.

mViewPager is bind to the Tablayout.

Under MainActivity TabLayout will display the name of Tabs.

TabGroupAdapter

 public class TabGroupAdapter extends FragmentPagerAdapter {

    private ArrayList<Fragment> fragmentList = new ArrayList<Fragment>();
    private ArrayList<String> fragment_name;

    public TabGroupAdapter(FragmentManager fm, ArrayList<String> name, ArrayList<Fragment> list) {
        super(fm);
        this.fragmentList = list;
        this.fragment_name = name;
    }

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return fragment_name.get(position);
    }
}

In TabGroupAdapter you would pass a List of fragments(or single fragment) and list of fragments name(or single name) as arguments in the Constructor.

IndividualFragment(s) will act like a individual Tab instead of Activity.

RootFragment will be acting as a container for other fragments( First Fragment and Second Fragment)

Root Fragment

public  class RootFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.root_fragment, container, false);
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.root_frame, new FirstFragment());
        fragmentTransaction.commit();
        return view;
    }
}

First Fragment

public  class FirstFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.first_fragment, container, false);

        Button btn = (Button) view.findViewById(R.id.btn);

        btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            //use the "root frame" defined in
            //"root_fragment.xml" as the reference to replace fragment

            fragmentTransaction.replace(R.id.root_frame, new SecondFragment());
            /*
             * allow to add the fragment 
             * to the stack and return to it later, by pressing back
             */
           fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    });
    }
}

Second Fragment

public  class SecondFragment extends Fragment {

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

Individual(s) Fragment

public  class IndividualFragment1 extends Fragment {

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



public  class IndividualFragment2 extends Fragment {

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

In OnCreateView method you would set a layout of a Tab .

You won't have to use the getTabHost() method.

Let me know if you persist any problem.

Whenever you want to dynamically change or update the Tabs in View Pager just add or remove item from fragmentList and call this method mTabGroupAdapter.notifyDataSetChanged(); inside MainActivity.

Add these dependencies to your project:

compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'

First change your Main activity must be extended from AppCompatActivity.

Than change your main activity's layout like below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinatorlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".Main">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbarlayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <include
            layout="@layout/toolbar_default"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:tabGravity="fill"
            app:tabMaxWidth="0dp"
            app:tabIndicatorHeight="4dp"
            app:tabMode="fixed"
            app:tabIndicatorColor="@android:color/white"
            android:background="@color/AppPrimary"/>
    </android.support.design.widget.AppBarLayout>

   <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".dashboard.DashboardActivity"
    tools:showIn="@layout/activity_dashboard">


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

</RelativeLayout>

</android.support.design.widget.CoordinatorLayout>

And here's a toolbar layout example. You can customize however you want.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar_main"
    style="@style/Widget.MyApp.Toolbar.Solid"
    android:layout_width="match_parent"
    android:layout_height="@dimen/abc_action_bar_default_height_material"
    android:background="@color/AppPrimary"
    app:contentInsetEnd="16dp"
    app:contentInsetStart="16dp" />

Than you need to create fragments which you'll use in your tabs instead of activities which you use for tabs. In this case this'll your Status Activity if i'm not wrong.

Define a StatusFragment like below:

public class StatusFragment extends Fragment
{
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // this is your Status fragment. You can do stuff which you did in     Status activity
    }
}

Than you need to define a tabs adapter which you'll bind with your tabs and convert your TabHost to Fragment/Fragment manager type. Titles string array contains strings which you'll show in your tabs indicator. Such as "Status, My Assume Tab, My awesome tab 2

public class DashboardTabsAdapter extends FragmentPagerAdapter {
    private String[] mTitles;

    public DashboardTabsAdapter(FragmentManager fm, String[] titles) {
        super(fm);
        this.mTitles = titles;
    }

    @Override
    public Fragment getItem(int position) {
        return new StatusFragment();
        // You can define some other fragments if you want to do different types of operations in your tabs and switch this position and return that kind of fragment.
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles[position];
    }
}

And finally in your Main activity find your view pager, tabs create a new adapter and bind them.

        final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        final DashboardTabsAdapter dashboardTabsAdapter = new DashboardTabsAdapter(getSupportFragmentManager(), getResources().getStringArray(R.array.tab_titles));
        mViewPagerMain = (ViewPager) findViewById(R.id.viewpager_main);
        mViewPagerMain.setOffscreenPageLimit(3);
        mViewPagerMain.setAdapter(dashboardTabsAdapter);
        tabLayout.setupWithViewPager(mViewPagerMain);

Edit: You'll no longer need TabHost and TabActivity any more. Your tab grup activity will be your ViewPager which handles screen changes and lifecycle of fragments inside. If you need to get this activity from fragments you can use getActivity() method and cast it to your activity and use it's public methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!