【问题标题】:Go to next page in ViewPager转到 ViewPager 中的下一页
【发布时间】:2016-04-13 13:39:28
【问题描述】:

我的 MainActivity 中有一个 ViewPager。其中的每一页都是一个片段。因此,每次我向右或向左滑动时,都会创建一个新的片段实例,并相应地更新片段视图。

我还有两个按钮:LEFTRIGHT 用于导航。这些按钮在 Fragment 中,而不是在 Activity 中。用户可以滑动或按下相关按钮在页面之间导航。

问题来了:由于我正在通过 MainActivity 更改视图,如何检测 Activity 中这些按钮的 onClick 事件以更新片段?

这是PagerAdapter 类(从各处删除了所有不相关的代码):

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);
    }

这是PlaceHolderFragment 类:

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;
    }
}

更多信息: 我必须将导航按钮保留在片段本身而不是活动中。

【问题讨论】:

  • 将按钮附加到 mainactivity 布局。
  • 在你的活动中添加按钮而不是在片段中。分享你的活动 xml,我会告诉你如何添加
  • @MustanserIqbal,是的,这是一个选项,但我必须将按钮保留在片段本身中。还有其他解决方法吗?
  • 编写一个接口并在您的 mainactivity 和片段的 onClick 中实现该接口,为活动实现的方法提供回调。

标签: android android-fragments android-viewpager


【解决方案1】:

在您的片段中编写一个界面,例如:

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);
            }
        });
     }   

在你的主要活动中:

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;
        }
    }
}

【讨论】:

  • 好主意。完美运行。
  • 代码yourButtons.setOnClickListener(...) 似乎在任何方法之外。你的意思是它成为onAttach() 方法的一部分吗?
  • 应检查页数
【解决方案2】:

对于 KotlinViewPager2

上一页:

val currPos: Int = xyzViewPager.currentItem
if (currPos != 0) {
   xyzViewPager.currentItem = currPos - 1
}

下一页:

val currPos: Int = xyzViewPager.currentItem
if ((currPos + 1) != xyzViewPager.adapter?.count) {
    xyzViewPager.currentItem = currPos + 1
}

【讨论】:

    【解决方案3】:

    在你的活动中创建一个公共方法

    public void swipeRight(int x){
        if(x < totalNumberOfFragment){
            viewPager.setCurrentItem(x + 1);
        }
    }
    
    public void swipeLeft(int x){
        if(x > 0){
            viewPager.setCurrentItem(x - 1);
        }
    }
    

    您可以从片段按钮的点击操作中调用这些方法

    RightButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Yes 
                ((YourActivityClassName)getActivity()).swipeRight(position);
            }
        });
    

    对 LeftButton 做同样的事情

    YourActivityClassName - 持有这个 viewPager 片段的 Activity。

    position - 当前片段的位置。

    【讨论】:

    • 这是错误的做法,activity应该是监听fragment交互,而不是直接调用函数。这种方式更有可能让您陷入活动/片段生命周期异常。拉姆的回答绝对是正确的做法。
    【解决方案4】:

    使用 kotlin 扩展函数:

    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
    }
    

    【讨论】:

      【解决方案5】:

      您可以在活动 xml 中添加按钮,如下所示

      <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>
      

      【讨论】:

        【解决方案6】:

        您可以在父级Activity 中创建特殊方法,如下所示:

        public class PagerActiviy extends Activity {
            ...
            public void onFragmentNavigationButtonClick(View button) {
                // Do your stuff here
            }
            ...
        }
        

        然后在您的片段中,您可以使用getActivity() 方法获取您的父级Activity,将其转换为实际类型并调用该方法:

        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;
            }
        }
        

        作为旁注,我应该从您的示例中补充一点,不清楚为什么您需要将导航按钮保留在片段中并且不能将它们移动到 Activity 并在那里管理它们。

        【讨论】:

          【解决方案7】:

          您可以在片段内单击按钮时发送广播,如下所示:

          Intent intent = new Intent();
                  intent.setAction(NUMBER_OF_RECEIVER_NEXT);
                  getActivity().sendBroadcast(intent);
          

          然后在您的主要活动中,您捕获 Intent 并将寻呼机的当前位置设置为所需的数字

          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");
                      }
                  }
              }
          

          别忘了设置一个

          private static final String NUMBER_OF_RECEIVER_NEXT = "nextPage";
          

          在主要活动和片段中,当然还有注册、注销接收器到 onResume 和 onPause 方法。

          还在 onCreate 方法中为接收者添加一个意图过滤器,操作指定为 NUMBER_OF_RECEIVER_NEXT

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-12-22
            • 2011-12-05
            • 1970-01-01
            • 2012-12-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多