Reputation: 4576
I have a ViewPager
in my MainActivity. Every page in it is a Fragment. So, everytime I swipe right or left, a new instance of the fragment is created and the fragment view is updated accordingly.
I also have two buttons: LEFT
and RIGHT
for navigation. These buttons are inside the Fragment, not in the Activity. A user can either swipe or alternatively press the relevant button to navigate between the pages.
Here's the problem: Since I'm changing the views through my MainActivity, how do I detect the onClick
events of those buttons in the Activity in order to update the fragment?
Here's the PagerAdapter
class (Removed all the irrelevant code from everywhere):
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// logic part for the views.
return PlaceholderFragment.newInstance(sectionNumber, questionStatus, questionOrder, showNext, showPrevious);
}
And here's the PlaceHolderFragment
class:
public class PlaceholderFragment extends Fragment{
//some global variables
public static PlaceholderFragment newInstance(int sectionNumber, int questionStatus, String questionOrder, boolean showNext, boolean showPrevious) {
PlaceholderFragment fragment = new PlaceholderFragment();
//setting up the arguments
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.explanation_fragment, container, false);
//code for filling up all the views
RightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//can I do something here?
}
});
return rootView;
}
}
MORE INFO: I have to keep the navigation buttons in the fragment itself and not in the activity.
Upvotes: 9
Views: 24288
Reputation: 2060
Use kotlin extension functions:
fun ViewPager2.nextPage(smoothScroll: Boolean = true): Boolean {
if ((currentItem + 1) < adapter?.itemCount ?: 0) {
setCurrentItem(currentItem + 1, smoothScroll)
return true
}
//can't move to next page, maybe current page is last or adapter not set.
return false
}
fun ViewPager2.previousPage(smoothScroll: Boolean = true): Boolean {
if ((currentItem - 1) >= 0) {
setCurrentItem(currentItem - 1, smoothScroll)
return true
}
//can't move to previous page, maybe current page is first or adapter not set.
return false
}
Upvotes: 6
Reputation: 14618
For Kotlin and ViewPager2
previous page:
val currPos: Int = xyzViewPager.currentItem
if (currPos != 0) {
xyzViewPager.currentItem = currPos - 1
}
next page:
val currPos: Int = xyzViewPager.currentItem
if ((currPos + 1) != xyzViewPager.adapter?.count) {
xyzViewPager.currentItem = currPos + 1
}
Upvotes: 6
Reputation: 2790
You can send a broadcast upon button click inside the fragment like below:
Intent intent = new Intent();
intent.setAction(NUMBER_OF_RECEIVER_NEXT);
getActivity().sendBroadcast(intent);
Then in your main activity you catch the Intent and you set the current position of the pager to the desired number
private class broadcastReceived extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String actionGet = intent.getAction();
if(actionGet.equals(NUMBER_OF_RECEIVER_NEXT)){
mPager.setCurrentItem(1);
Log.e("IntentNextPage","Received");
}
}
}
Do not forget to set a
private static final String NUMBER_OF_RECEIVER_NEXT = "nextPage";
in both main activity and fragment and of course to register,unregister receiver to onResume and onPause methods.
Also add an intent filter to the receiver in onCreate methd with the action specified as NUMBER_OF_RECEIVER_NEXT
Upvotes: 0
Reputation: 1308
In your fragment write one interface like:
public class PlaceholderFragment extends Fragment{
private OnButtonClickListener mOnButtonClickListener;
interface OnButtonClickListener{
void onButtonClicked(View view);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mOnButtonClickListener = (OnButtonClickListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(((Activity) context).getLocalClassName()
+ " must implement OnButtonClickListener");
}
}
yourButtons.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnButtonClickListener.onButtonClicked(v);
}
});
}
And in your mainactivity:
class MainActivity extends AppCompatActivity implements OnButtonClickListener{
@Override
void onButtonClicked(View view){
int currPos=yourPager.getCurrentItem();
switch(view.getId()){
case R.id.leftNavigation:
//handle currPos is zero
yourPager.setCurrentItem(currPos-1);
break;
case R.id.rightNavigation:
//handle currPos is reached last item
yourPager.setCurrentItem(currPos+1);
break;
}
}
}
Upvotes: 21
Reputation: 37
Make a public method in your activity
public void swipeRight(int x){
if(x < totalNumberOfFragment){
viewPager.setCurrentItem(x + 1);
}
}
public void swipeLeft(int x){
if(x > 0){
viewPager.setCurrentItem(x - 1);
}
}
You can call these method from your fragment button's click action
RightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Yes
((YourActivityClassName)getActivity()).swipeRight(position);
}
});
And do same for LeftButton
YourActivityClassName - Activity which is holding this viewPager fragment.
position - position of your current fragment.
Upvotes: 3
Reputation: 679
You can create special method in your parent Activity
like following:
public class PagerActiviy extends Activity {
...
public void onFragmentNavigationButtonClick(View button) {
// Do your stuff here
}
...
}
Then in your fragments you can get your parent Activity
with getActivity()
method, cast it to the actual type and call the method:
public class PlaceholderFragment extends Fragment{
...
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.explanation_fragment, container, false);
//code for filling up all the views
RightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((PagerActvity) getActivity()).onFragmentNavigationButtonClick(v);
}
});
return rootView;
}
}
As a side note I should add that from your example it's not clear why do you need to keep your navigation buttons in the fragments and can't move them to the Activity
and manage them there.
Upvotes: 0
Reputation: 3711
You can add button in your activities xml as follows
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
</LinearLayout>
<ImageView
android:id="@+id/leftNavigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:padding="10dp"
android:src="@drawable/ic_chevron_left_black_24dp"
android:visibility="gone" />
<ImageView
android:id="@+id/rightNavigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_weight="0"
android:gravity="center"
android:padding="10dp"
android:src="@drawable/ic_chevron_right_black_24dp" />
</FrameLayout>
Upvotes: 0