解決ViewPager setCurrentItem 時閃太快

gpyq6055 8年前發布 | 43K 次閱讀 ViewPager Android開發 移動開發

ViewPager 使用 setCurrentItem 的時候,如果兩個頁面相聚比較遠,比如從第一個頁面跳到第六個頁面,就會閃一下,解決辦法就是把界面滑動的效果的 duration 設置為0,但是ViewPager 內部的 mScroller 無法正常獲得,所以可以嘗試采用 反射的方法:

先自定一個MScroller

方便調節 duration

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

定義一個輔助類

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


}

這樣每次設置頁面的時候,通過 helper 就可以自動選擇是否有時間間隔了。

但是這樣有點麻煩,每次還要手動改,而且使用TabLayout的話,它會自動調用ViewPager的方法,無法使用Helper,所以可以采用自定一個一個 ViewPager

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

這樣用起來就很方便了。

fragment布局

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

MFragment

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

activity 布局

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

這里使用了一個 tabLayout ,它是在 design 包里的

需要在 gradle 文件加:

compile 'com.android.support:design:23.4.0'

activity

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

}

 

來自:http://www.jianshu.com/p/ae360ffcbcda

 

 本文由用戶 gpyq6055 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!