自定义ViewPagerIndicator:100行代码实现两种可滑动指示器

来源:互联网 发布:手机加油软件代理 编辑:程序博客网 时间:2024/06/04 19:34

按照惯例先上图,一种是三角形,一种是最常用的下划线





实现思路,主要是在onPageScroll里面进行指示器滑动距离和父容器滑动距离的计算,然后进行滑动,滑动解决了其他就比较简单了。

顶部就是自定义的ViewPagerIndicator,下面就是Fragment+FragmentPagerAdagter


主MainActivity代码,就是常规的ViewPagerIndicator结合Fragment

public class IndicatorActivity extends AppCompatActivity {    private ViewPagerIndicator indicator;    private ViewPager mViewPager;    private List<Fragment> mList = new ArrayList<>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_indicator);        mList.add(TitleFragment.newInstance("标题1"));        mList.add(TitleFragment.newInstance("标题2"));        mList.add(TitleFragment.newInstance("标题3"));        mList.add(TitleFragment.newInstance("标题4"));        mList.add(TitleFragment.newInstance("标题5"));        mList.add(TitleFragment.newInstance("标题6"));        mList.add(TitleFragment.newInstance("标题7"));        mList.add(TitleFragment.newInstance("标题8"));        mList.add(TitleFragment.newInstance("标题9"));        indicator = (ViewPagerIndicator) findViewById(R.id.indicator_activity);        indicator.setSelected_indicator(ViewPagerIndicator.LINE);//使用三角形        indicator.selectText(0);//默认选中第一个        mViewPager = (ViewPager) findViewById(R.id.viewpager_indicator);        mViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), mList));        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {                indicator.move(position, positionOffset); //position当前fragment,offset滑动值0-1            }            @Override            public void onPageSelected(int position) {                indicator.selectText(position);//textview选中效果            }            @Override            public void onPageScrollStateChanged(int state) {            }        });    }}

Fragment里面就一个textview很简洁

public class TitleFragment extends Fragment {    private static final String PARAM1 = "param1";    private String mParam1;    private Context mContext;    private callback mCb;    public static TitleFragment newInstance(String text) {        TitleFragment fragment = new TitleFragment();        Bundle bundle = new Bundle();        bundle.putString(PARAM1, text);        fragment.setArguments(bundle);        return fragment;    }    @Override    public void onAttach(Context context) {        super.onAttach(context);        if (context != null) {            mContext = context;            if (context instanceof callback) {                mCb = (callback) context;            }        }    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (getArguments() != null) {            mParam1 = getArguments().getString(PARAM1);        }    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        //不写xml文件        TextView textView = new TextView(mContext);        textView.setText(mParam1);        textView.setGravity(Gravity.CENTER);        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);        lp.gravity = Gravity.CENTER;        textView.setLayoutParams(lp);        return textView;    }    @Override    public void onDetach() {        super.onDetach();        mCb = null;    }    public interface callback {        void success(String msg);    }}

Adapter没什么好说的

public class ViewPagerAdapter extends FragmentPagerAdapter {    private List<Fragment> mList = new ArrayList<>();    public ViewPagerAdapter(FragmentManager fm, List<Fragment> mList) {        super(fm);        this.mList = mList;    }    @Override    public Fragment getItem(int position) {        return mList.get(position);    }    @Override    public int getCount() {        return mList.size();    }}

主角自定义的ViewPagerIndicator,继承的LinnerLayout,在里面加TextView的方式,加了挺多注释的应该很好理解

public class ViewPagerIndicator extends LinearLayout {    private static final String TAG = "ViewPagerIndicator";    public static final int TRIANGLE = 1;//三角形    public static final int LINE = 2;//下划线    public static int selected_indicator = TRIANGLE;//要使用的指示器    private int mScreenWidth;//屏幕宽    private int mTitleWidth;//每个标题宽    private int mTriangleWidth;//三角宽    private int mInitLeftMargin;//初始化的三角x位置    private int mMoveMargin = 0;//计算出来的移动x位置    private int mTriangleY;//三角形底部的位置Y    private int mTitleCount = 9;//标题总数    private int mVisibableCount = 3;//一屏显示标题数量    public ViewPagerIndicator(Context context) {        this(context, null);    }    public ViewPagerIndicator(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        mScreenWidth = wm.getDefaultDisplay().getWidth();        //初始化一些指示器的宽高参数        mTitleWidth = mScreenWidth / 3;//默认每个标题占屏幕三分之一宽        mTriangleWidth = mScreenWidth / 3 / 6;//一个三角形底边占每个标题六分之一        mInitLeftMargin = mScreenWidth / 3 / 2 - (mTriangleWidth / 2);//初始化第一次三角在标题下居中        mTriangleY = DensityUtil.dip2px(context, 50);//xml标题栏高50dp        Log.d(TAG, mScreenWidth + "-" + mTriangleWidth + "-" + mInitLeftMargin);        //获取标题数量        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator);        mTitleCount = array.getInt(R.styleable.ViewPagerIndicator_titleCount, mTitleCount);        array.recycle();        //生成标题        for (int i = 0; i < mTitleCount; i++) {            TextView textView = new TextView(context);            textView.setText("标题" + (i + 1));            textView.setTextColor(getResources().getColor(R.color.titile_text_color));            textView.setGravity(Gravity.CENTER);            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(mScreenWidth / mVisibableCount, ViewGroup.LayoutParams.MATCH_PARENT);            textView.setLayoutParams(lp);            addView(textView);        }    }    //指示器+容器滚动    public void move(int pos, float offset) {        if (selected_indicator == TRIANGLE) {            mMoveMargin = (int) (mInitLeftMargin + pos * mTitleWidth + (offset * mTitleWidth));//三角形移动        }else if (selected_indicator == LINE) {            mMoveMargin = (int) (pos * mTitleWidth + (offset * mTitleWidth));//线移动        }        //容器滚动,在一屏倒数第二个才允许        if (pos >= mVisibableCount - 2 && pos < mTitleCount - 2) {            scrollTo((int) ((pos - (mVisibableCount - 2)) * mTitleWidth + (mTitleWidth * offset)), 0);        }        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //画三角形画笔        Paint paint = new Paint();        paint.setColor(getResources().getColor(R.color.master_color));        paint.setStyle(Paint.Style.FILL);        paint.setStrokeWidth(10.0f);//线宽        if (selected_indicator == TRIANGLE) {            if (mMoveMargin == 0) {//不是第一次draw,使用移动的值                mMoveMargin = mInitLeftMargin;            }            //直角三角形            Path path = new Path();            path.moveTo(mMoveMargin, mTriangleY);//左点            path.lineTo(mMoveMargin + mTriangleWidth, mTriangleY);//右点            path.lineTo(mMoveMargin + (mTriangleWidth / 2), mTriangleY - (mTriangleWidth / 2));//上点            path.close();            canvas.drawPath(path, paint);        }else if (selected_indicator == LINE) {            canvas.drawLine(mMoveMargin, mTriangleY, mTitleWidth + mMoveMargin, mTriangleY, paint);        }    }    public void setSelected_indicator(int selected_indicator) {        this.selected_indicator = selected_indicator;    }    //选中改变字体颜色    public void selectText(int position) {        TextView textView;        for (int i = 0; i < mTitleCount; i++) {            textView = (TextView) getChildAt(i);            if (position == i) {                textView.setTextColor(getResources().getColor(R.color.colorAccent));            } else {                textView.setTextColor(getResources().getColor(R.color.titile_text_color));            }        }    }}


代码基本贴完了,就不上传工程了,写了大半天时间,有些问题可能没考虑到,见谅一下,毕竟才一百行,不过麻雀虽小五脏俱全啊。







0 0