Reputation: 1513
I'm a beginner Android developer (I'm a Windows developer since 1995) and I'm developing my first app. I have a two dimensional array of data (something like a[2][]). Basically it represents three different set of data that need to be represented on the device screen. Unfortunately, while two of them can be represented using a grid, the third set must be represented in a completely different way. So what I need is a three-paged activity; in the first two I would like to use a common layout, populated with the needed data, while in the third page I have to use a completely different layout.
I found this: ViewPager Without Fragments, but unfortunately I am confused on where to place code to handle user input on the three pages.
Being a beginner on Android I'm actually a bit confused on what should be the general approach in such a situation. In my usual developement experience I would create a window with a tabbed control, three tabs, grids in the first two and some custom control in the third. These three controls would live in the same "scope" (my window) and would be populated during window loading.
I understand that in Android I have to follow a completely different approach, but, as I said I'm confused: fragments? No fragments? What else?
Thank you!
Upvotes: 0
Views: 8707
Reputation: 2136
To implement multiple pages within the same activity, you need to use fragments. In your case, we will need 3 fragments. Your activity layout file should contain a ViewPager which will hold the fragments in the activity. You can also add a TabLayout if you want the fragments to also be accessible via tabs. A sample Activity layout can be as follows:
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="your.package.name.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:titleTextColor="@color/colorAccent"
/>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:background="@color/grey"
app:tabGravity="fill"
app:tabIndicatorColor="@color/colorAccent"
app:tabIndicatorHeight="5dp"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@color/black"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
After doing this, you need to create a FragmentPagerAdapter class in your Activity Class. This adapter will manage the instantiation of your ViewPager which holds the fragments in the Activity. Here is a sample FragmentPagerAdapter SubClass
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
Log.d(LOG_TAG, "postion " + position);
if (position == 0) {
return Fragment1.newInstance(position + 1);
} else if (position == 1) {
return Fragment2.newInstance(position + 1);
} else {
return Fragment3.newInstance(position + 1);
}
}
@Override
public int getCount() {
// Show 3 total pages.
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return "Fragment1";
case 1:
return "Fragment2";
case 2:
return "Fragment3";
}
return null;
}
}
This done, you can now get the reference to the ViewPager in the Activity onCreate method and the set the ViewPager adapter as follows
@Override
protected void onCreate(Bundle savedInstanceState) {
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mSectionsPagerAdapter);
// setting the views to be accessed through tabs
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int currentTab = tab.getPosition();
viewPager.setCurrentItem(currentTab);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
Hope this clear for you. For more information, you can also check here
Upvotes: 2
Reputation: 38595
You can handle user input within your Activity, or you can break it up into Fragments. Both are described below.
Activity
The problem is usually you obtain references to Views
in your layout during the Activity's onCreate()
method and perform whatever setup (adding OnClickListener
s, etc), but that's not really possible in this case because at that moment your ViewPager
hasn't loaded any pages and the views on those pages aren't in the view hierarchy yet. (Android's view and layout system can be rather confusing when ViewPager
s are involved).
Instead you would have to obtain the references and perform your setup inside of instantiateItem()
of your adapter, and presumably invalidate those references in destroyItem()
.
Fragments
The issue described above is likely the reason Fragments are supported directly in the framework (using FragmentPagerAdapter
or FragmentStatePagerAdapter
). With a Fragment
for each page, you can obtain references to views on that page and perform setup inside of onCreateView()
(or onViewCreated()
), and the business logic could also be encapsulated in the fragment. Basically, you don't have to worry about the existence of the views relative to the timing of these callbacks, unlike with the Activity's onCreate()
.
One other benefit is that by having logic encapsulated in separate Fragments, you have a degree of modularity with your app. If you can envision your app on a larger screen having perhaps two (or even all three) of your "pages" visible at once, then it's probably better to use Fragments from the beginning.
Upvotes: 1