I am using ViewPager
, FragmentStatePagerAdapter
and Fragment
.
How can I load each fragment with it's functionality (first initialization, button handlers)?
I manage to make the buttons to work but I had to move all the handles in the main activity. How can I keep the functionality in the fragment?
Here is my adapter:
public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
// Our object is just an integer :-P
args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
fragment.setArguments(args);
return fragment;
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0: return "A";
case 1: return "B";
case 2: return "C";
}
return "Tab " + (position + 1);
}
}
And this is the fragment:
public class DemoObjectFragment extends Fragment {
public static final String ARG_OBJECT = "object";
int mNum;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.
View rootView = inflater.inflate(R.layout.activity_page, container, false);
//((TextView) rootView.findViewById(android.R.id.text1)).setText(
// Integer.toString(args.getInt(ARG_OBJECT)));
return rootView;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
Update: Here is the activity_page.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/panel_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#fffaffff"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".GuessActivity">
<TextView
android:id="@+id/text1"
android:text="@string/lorem_ipsum"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/button_validate"
android:layout_width="wrap_content"
android:layout_height="@dimen/guess_height"
android:layout_alignParentRight="true"
android:onClick="validateGuess"
android:text="@string/button_validate" />
<TextView
android:id="@+id/text2"
android:text="@string/guess_success"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#008000"
android:visibility="gone"/>
</LinearLayout>
</FrameLayout>
Your question doesn't seem to be about swiping really, but rather how to keep code relating to a particular screen grouped together.
Currently you use the onClick
attribute in your activity layout, on elements where you want to handle the click. The contract for this attribute requires a public void method in your activity, taking a single View
object as parameter, with the same name as the value of the attribute. E.g. if you had:
<View ...
android:onClick="onButtonPress" />
you'd need the corresponding method in your activity:
public void onButtonPress(View view) {
...
}
Assuming that each of your fragments have a different UI (a different XML layout) and you want to keep the logic for each one inside the fragment, I would start with a stricter naming convention.
Currently your DemoObjectFragment's layout is called activity_page.xml
. Consider reserving activity_
prefix for layouts that you will use in your activities. Instead try fragment_demo_object.xml
for this particular fragment.
You instantiate this fragment's layout in onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
which is correct. Before you return the root view, you can find your views, as you have done, though they are commented out.
private Button validateButton;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_page, container, false);
validateButton = (Button) rootView.findById(R.id.button_validate);
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
validateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
validateInput();
}
});
}
private void validateInput() {
// validate whatever you want to validate
}
In this case, the logic for the UI on a particular fragment is only on that fragment.