为了满足伸手党的需求,先贴上代码
- 源码
baselinkPageChangeListener.java
public class baselinkPageChangeListener implements ViewPager.OnPageChangeListener {
private final ViewPager linkViewPager;
private final ViewPager selfViewPager;
private int marginX = 0;
public baselinkPageChangeListener(ViewPager selfViewPager,ViewPager linkViewPager){
this.linkViewPager = linkViewPager;
this.selfViewPager = selfViewPager;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//计算移动值
marginX = ((selfViewPager.getWidth() + selfViewPager.getPageMargin()) * position
+ positionOffsetPixels) * (linkViewPager.getWidth() + linkViewPager.getPageMargin()) /
(selfViewPager.getWidth() + selfViewPager.getPageMargin());
if (linkViewPager.getScrollX() != marginX) {
linkViewPager.scrollTo(marginX, 0);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
Activity.java
public class ViewpagerActivity extends AppCompatActivity {
private ViewPager mViewpager1;
private ViewPager mViewpager2;
private ZoomOutPageTransformer zoomOutPageTransformer;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpage1);
initView();
}
private void initView() {
mViewpager1 = findViewById(R.id.viewpager1);
mViewpager2 = findViewById(R.id.viewpager2);
mViewpager1.setAdapter(new TopViewPgaerAdapter(this));
mViewpager2.setAdapter(new BottomViewPagerAdapter(this));
mViewpager1.setOffscreenPageLimit(5);
mViewpager2.setOffscreenPageLimit(5);
baselinkPageChangeListener baselinkPageChangeListener = new baselinkPageChangeListener(mViewpager1, mViewpager2);
mViewpager1.addOnPageChangeListener(baselinkPageChangeListener);
baselinkPageChangeListener baselinkPageChangeListener1 = new baselinkPageChangeListener(mViewpager2, mViewpager1);
mViewpager2.addOnPageChangeListener(baselinkPageChangeListener1);
}
private static class TopViewPgaerAdapter extends PagerAdapter {
private Context context;
public TopViewPgaerAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return 5;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
// 判断是不是同一个视图
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View inflate = LayoutInflater.from(context).inflate(R.layout.item_top, container, false);
container.addView(inflate);
return inflate;
}
}
private static class BottomViewPagerAdapter extends PagerAdapter {
private Context context;
public BottomViewPagerAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return 5;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
// 判断是不是同一个视图
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View inflate = LayoutInflater.from(context).inflate(R.layout.item_bottom, container, false);
container.addView(inflate);
return inflate;
}
}
}
activity_viewpager.xml
item_top.xml
item_bottom.xml
- 分析
实现思路: 通过ViewPager的OnPageChangeListener监听回调的onPageScrolled(int position, float positionOffset, int positionOffsetPixels)方法来实现联动效果,关键代码如下:
selfViewPager.getWidth() + selfViewPager.getPageMargin() 偏移比例
(selfViewPager.getWidth() + selfViewPager.getPageMargin()) * position + positionOffsetPixels 表示当前手指触摸的ViewPager的总偏移距离
linkViewPager.getWidth() + linkViewPager.getPageMargin() 表示联动的ViewPager的大小
//计算移动值'
//
marginX = ((selfViewPager.getWidth() + selfViewPager.getPageMargin()) * position
+ positionOffsetPixels) * (linkViewPager.getWidth() + linkViewPager.getPageMargin()) /
(selfViewPager.getWidth() + selfViewPager.getPageMargin());
if (linkViewPager.getScrollX() != marginX) {
linkViewPager.scrollTo(marginX, 0);
}
测试
问题
问题产生原因分析
暂未找到原因
解决方案(先上代码)
activity_viewpager.xml
MyLinearLayout.java
public class MyLinearLayout extends LinearLayout {
private MyLinearLayout otherLinearLayout;
public MyLinearLayout(Context context) {
super(context);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public LinearLayout getOtherLinearLayout() {
return otherLinearLayout;
}
public void setOtherLinearLayout(MyLinearLayout otherLinearLayout) {
this.otherLinearLayout = otherLinearLayout;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (otherLinearLayout != null) {
otherLinearLayout.fakeTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
}
public void fakeTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
}
Activity.java
public class ViewPagerActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpage);
MyLinearLayout mLinear1 = findViewById(R.id.mLinear1);
MyLinearLayout mLinear2 = findViewById(R.id.mLinear2);
mLinear1.setOtherLinearLayout(mLinear2);
mLinear2.setOtherLinearLayout(mLinear1);
ViewPager mViewpager1 = findViewById(R.id.viewpager1);
ViewPager mViewpager2 = findViewById(R.id.viewpager2);
mViewpager1.setAdapter(new TopViewPgaerAdapter(this));
mViewpager2.setAdapter(new BottomViewPagerAdapter(this));
mViewpager1.setOffscreenPageLimit(5);
mViewpager2.setOffscreenPageLimit(5);
}
private static class TopViewPgaerAdapter extends PagerAdapter {
private Context context;
public TopViewPgaerAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return 5;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
// 判断是不是同一个视图
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View inflate = LayoutInflater.from(context).inflate(R.layout.item_top, container, false);
container.addView(inflate);
return inflate;
}
}
private static class BottomViewPagerAdapter extends PagerAdapter {
private Context context;
public BottomViewPagerAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return 5;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
// 判断是不是同一个视图
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View inflate = LayoutInflater.from(context).inflate(R.layout.item_parent, container, false);
container.addView(inflate);
return inflate;
}
}
}
问题: 使用上述代码虽然解决了联动问题,但是在多指滑动时会出现如下问题
解决方案:
禁用多指触控 android:splitMotionEvents="false"
关键代码:
public void setOtherLinearLayout(MyLinearLayout otherLinearLayout) {
this.otherLinearLayout = otherLinearLayout;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (otherLinearLayout != null) {
otherLinearLayout.fakeTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
}
public void fakeTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
}
可能连你页没有想到,竟然能使用这么少的代码的量解决了联动的问题,而且滑动起来还很丝滑,viewpager2也是使用这种方式来解决的,而且Viewpager2运行起来更加的丝滑,毫无违和感,这一切还得归功于享学课堂的Colin老师,目前网上大部分的教程在viewpager上实现双联动都是使用滑动监听回调和继承viewpager的方式来解决问题。自从加入了享学课堂,才两个多月老板就给涨了两千薪水,之前同事做不出来的功能,我参考享学课堂老师讲的都解决了,哈哈,以后我就要跟着Colin老师学习下去。
废话不多说,viewpager2实现双联动直接上代码
activity_viewpager2.xml
fragment_test.xml
ViewPager2Activity.java
public class ViewPager2Activity extends AppCompatActivity {
private List fragments = new ArrayList<>();
private List fragments2 = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager2 viewPager = findViewById(R.id.viewPager);
ViewPager2 viewPager2 = findViewById(R.id.viewPager2);
MyLinearLayout linearLayout1 = findViewById(R.id.linearLayout1);
MyLinearLayout linearLayout2 = findViewById(R.id.linearLayout2);
linearLayout1.setOtherLinearLayout(linearLayout2);
linearLayout2.setOtherLinearLayout(linearLayout1);
fragments.add( new OneFragment());
fragments.add( new TwoFragment());
fragments.add( new ThreeFragment());
fragments2.add( new OneFragment());
fragments2.add( new TwoFragment());
fragments2.add( new ThreeFragment());
viewPager.setAdapter(new ViewPagerAdapter(this,fragments));
viewPager2.setAdapter(new ViewPagerAdapter(this,fragments2));
}
}
ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStateAdapter {
private final List fragments;
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List fragments) {
super(fragmentActivity);
this.fragments = fragments;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments == null ? 0 : fragments.size();
}
}
OneFragment.java
public class TestFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_test, container, false);
}
}
TwoFragment.java
public class TwoFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_test, container, false);
}
}
ThreeFragment.java
public class ThreeFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_test, container, false);
}
}
效果:
看到没,要多丝滑,就有多丝滑,而且viewpager和viewpager2都是可以通用的,简简单单的代码就实现了,这一切都得感谢享学课堂的Colin老师,他们有着丰富的Android开发经验和前沿的开发技术,此刻都是独一无二的技术,好了,不多说了,我得找老师学习高级技术去了,学到了再分享给大家



