解决ViewPager setCurrentItem 时闪太快

gpyq6055 7年前
   <p>ViewPager 使用 setCurrentItem 的时候,如果两个页面相聚比较远,比如从第一个页面跳到第六个页面,就会闪一下,解决办法就是把界面滑动的效果的 duration 设置为0,但是ViewPager 内部的 mScroller 无法正常获得,所以可以尝试采用 反射的方法:</p>    <h2><strong>先自定一个MScroller</strong></h2>    <p>方便调节 duration</p>    <pre>  <code class="language-java">public  class MScroller extends Scroller {        private static final Interpolator sInterpolator = new Interpolator() {          public float getInterpolation(float t) {              t -= 1.0f;              return t * t * t * t * t + 1.0f;          }      };          public boolean noDuration;        public void setNoDuration(boolean noDuration) {          this.noDuration = noDuration;      }        public MScroller(Context context) {          this(context,sInterpolator);      }        public MScroller(Context context, Interpolator interpolator) {          super(context, interpolator);      }        @Override      public void startScroll(int startX, int startY, int dx, int dy, int duration) {          if(noDuration)              //界面滑动不需要时间间隔              super.startScroll(startX, startY, dx, dy, 0);          else              super.startScroll(startX, startY, dx, dy,duration);      }  }</code></pre>    <h2><strong>定义一个辅助类</strong></h2>    <pre>  <code class="language-java">public class ViewPageHelper {          ViewPager viewPager;        MScroller scroller;        public ViewPageHelper(ViewPager viewPager) {          this.viewPager = viewPager;          init();      }        public void setCurrentItem(int item){          setCurrentItem(item,true);      }        public MScroller getScroller() {          return scroller;      }          public void setCurrentItem(int item, boolean somoth){          int current=viewPager.getCurrentItem();          //如果页面相隔大于1,就设置页面切换的动画的时间为0          if(Math.abs(current-item)>1){              scroller.setNoDuration(true);              viewPager.setCurrentItem(item,somoth);              scroller.setNoDuration(false);          }else{              scroller.setNoDuration(false);              viewPager.setCurrentItem(item,somoth);          }      }        private void init(){          scroller=new MScroller(viewPager.getContext());          Class<ViewPager>cl=ViewPager.class;          try {              Field field=cl.getDeclaredField("mScroller");              field.setAccessible(true);              //利用反射设置mScroller域为自己定义的MScroller              field.set(viewPager,scroller);          } catch (NoSuchFieldException e) {              e.printStackTrace();          }catch (IllegalAccessException e){              e.printStackTrace();          }      }      }</code></pre>    <p>这样每次设置页面的时候,通过 helper 就可以自动选择是否有时间间隔了。</p>    <p>但是这样有点麻烦,每次还要手动改,而且使用TabLayout的话,它会自动调用ViewPager的方法,无法使用Helper,所以可以采用自定一个一个 ViewPager</p>    <pre>  <code class="language-java">public class SuperViewPager extends ViewPager {          private ViewPageHelper helper;        public SuperViewPager(Context context) {          this(context,null);      }        public SuperViewPager(Context context, AttributeSet attrs) {          super(context, attrs);          helper=new ViewPageHelper(this);      }        @Override      public void setCurrentItem(int item) {          setCurrentItem(item,true);      }        @Override      public void setCurrentItem(int item, boolean smoothScroll) {          MScroller scroller=helper.getScroller();          if(Math.abs(getCurrentItem()-item)>1){              scroller.setNoDuration(true);              super.setCurrentItem(item, smoothScroll);              scroller.setNoDuration(false);          }else{              scroller.setNoDuration(false);              super.setCurrentItem(item, smoothScroll);          }      }  }</code></pre>    <p>这样用起来就很方便了。</p>    <h3><strong>fragment布局</strong></h3>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?>  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical" android:layout_width="match_parent"      android:background="@color/colorPrimary"      android:layout_height="match_parent">          <TextView          android:gravity="center"          android:textSize="27sp"          android:textColor="#ffffff"          android:layout_centerInParent="true"          android:id="@+id/textview"          android:layout_width="match_parent"          android:layout_height="match_parent" />    </RelativeLayout></code></pre>    <h3><strong>MFragment</strong></h3>    <pre>  <code class="language-java">public class MFragemnt extends Fragment {            private String name="default";        public static MFragemnt newInstance(String name){          MFragemnt fragemnt=new MFragemnt();          fragemnt.name=name;          return fragemnt;      }        @Nullable      @Override      public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {          View view=inflater.inflate(R.layout.fragment_test,container,false);          TextView textView=(TextView)view.findViewById(R.id.textview);          textView.setText(name);          return view;      }  }</code></pre>    <h3><strong>activity 布局</strong></h3>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:tools="http://schemas.android.com/tools"      android:id="@+id/activity_main"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical"      android:paddingTop="@dimen/activity_vertical_margin"      tools:context="thereisnospon.viewpager.MainActivity">          <android.support.design.widget.TabLayout          android:id="@+id/tablayout"          android:layout_width="match_parent"          android:layout_height="wrap_content"></android.support.design.widget.TabLayout>          <thereisnospon.viewpager.SuperViewPager          android:id="@+id/viewPager"          android:layout_width="match_parent"          android:layout_height="match_parent"></thereisnospon.viewpager.SuperViewPager>      </LinearLayout></code></pre>    <p>这里使用了一个 tabLayout ,它是在 design 包里的</p>    <p>需要在 gradle 文件加:</p>    <pre>  <code class="language-java">compile 'com.android.support:design:23.4.0'</code></pre>    <h3>activity</h3>    <pre>  <code class="language-java">public class MainActivity extends AppCompatActivity {        private TabLayout tablayout;      private SuperViewPager viewPager;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          this.viewPager = (SuperViewPager) findViewById(R.id.viewPager);          this.tablayout = (TabLayout) findViewById(R.id.tablayout);            viewPager.setAdapter(new PageAdapter(getSupportFragmentManager()));          tablayout.setupWithViewPager(viewPager);      }          public static class PageAdapter extends FragmentPagerAdapter{            public PageAdapter(FragmentManager fm) {              super(fm);          }            @Override          public CharSequence getPageTitle(int position) {              return "P:"+position;          }            @Override          public Fragment getItem(int position) {              return MFragemnt.newInstance("Page:"+position);          }            @Override          public int getCount() {              return 5;          }      }    }</code></pre>    <p> </p>    <p>来自:http://www.jianshu.com/p/ae360ffcbcda</p>    <p> </p>