源码为了满足伸手党的需求,先贴上代码
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
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".viewpageruse1.ViewpagerActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager1"
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/viewpager1" />
androidx.constraintlayout.widget.ConstraintLayout>
item_top.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/teal_200"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
androidx.constraintlayout.widget.ConstraintLayout>
item_bottom.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/purple_500"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
androidx.constraintlayout.widget.ConstraintLayout>
分析
实现思路: 通过
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
<androidx.constraintlayout.widget.ConstraintLayout 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:splitMotionEvents="false"
tools:context=".viewpageruse1.Viewpager1Activity">
<com.ycy.customviewstudy.viewpageruse1.MyLinearLayout
android:id="@+id/mLinear1"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:background="@color/purple_500"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager1"
android:layout_width="match_parent"
android:layout_height="200dp" />
com.ycy.customviewstudy.viewpageruse1.MyLinearLayout>
<com.ycy.customviewstudy.viewpageruse1.MyLinearLayout
android:id="@+id/mLinear2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/mLinear1">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp" />
com.ycy.customviewstudy.viewpageruse1.MyLinearLayout>
androidx.constraintlayout.widget.ConstraintLayout>
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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.qdkj.viewpager2use.MyLinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1"
android:layout_marginBottom="10dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
com.qdkj.viewpager2use.MyLinearLayout>
<com.qdkj.viewpager2use.MyLinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_weight="1">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
com.qdkj.viewpager2use.MyLinearLayout>
LinearLayout>
fragment_test.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20dp"
android:text="@string/hello_blank_fragment" />
FrameLayout>
ViewPager2Activity.java
public class ViewPager2Activity extends AppCompatActivity {
private List<Fragment> fragments = new ArrayList<>();
private List<Fragment> 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<Fragment> fragments;
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> 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开发经验和前沿的开发技术,此刻都是独一无二的技术,好了,不多说了,我得找老师学习高级技术去了,学到了再分享给大家
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)