自定义简易的viewpager指示器
16lz
2021-01-26
package com.example.dxy.myapplication.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Build;import android.os.Bundle;import android.os.Parcelable;import android.support.annotation.RequiresApi;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import com.example.dxy.myapplication.R;import java.util.ArrayList;public class IndicatorView extends View implements ViewPager.OnPageChangeListener { //节点间距 private float mNodeGap; //节点个数 private int mNodeCount; //节点圆形半径 private float mNodeRadius; //节点默认填充颜色 private int mNodeColor; //移动节点填充颜色 private int mSelectedNodeColor; //当前选中节点的索引 private int mCurrentIndex = 0; //viewpager偏移量[0,1) private float mCurrentPositionOffset = 0; private ViewPager mViewPager; private Paint mNodePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mSelectedNodePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Context mContext; public IndicatorView(Context context) { this(context, null); } public IndicatorView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.mContext = context; obtainAttributes(context, attrs); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); this.mContext = context; obtainAttributes(context, attrs); } private void obtainAttributes(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView); mNodeGap = ta.getDimension(R.styleable.IndicatorView_node_gap, dp2px(10)); mNodeColor = ta.getColor(R.styleable.IndicatorView_node_default_color, Color.parseColor("#FFFF00")); mSelectedNodeColor = ta.getColor(R.styleable.IndicatorView_node_select_color, Color.parseColor("#FF0000")); mNodeRadius = ta.getDimension(R.styleable.IndicatorView_node_radius, dp2px(5)); mNodePaint.setColor(mNodeColor); mNodePaint.setStyle(Paint.Style.FILL); mSelectedNodePaint.setColor(mSelectedNodeColor); mSelectedNodePaint.setStyle(Paint.Style.FILL); ta.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mNodeCount <= 0) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } else { final int measureWidth = (int) ((mNodeCount - 1) * mNodeGap + mNodeCount * 2 * mNodeRadius); final int measureHeight = (int) (2 * mNodeRadius); setMeasuredDimension(measureWidth, measureHeight); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mNodeCount; i++) { canvas.drawCircle(mNodeRadius + i * mNodeGap + 2 * i * mNodeRadius, mNodeRadius, mNodeRadius, mNodePaint); } canvas.drawCircle(mNodeRadius + mCurrentIndex * mNodeGap + 2 * mCurrentIndex * mNodeRadius + (2 * mNodeRadius + mNodeGap) * mCurrentPositionOffset , mNodeRadius, mNodeRadius, mSelectedNodePaint); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { /** * position:当前View的位置 * mCurrentPositionOffset:当前View的偏移量比例.[0,1) */ this.mCurrentIndex = position; this.mCurrentPositionOffset = positionOffset; invalidate(); } @Override public void onPageSelected(int i) { //会出现mCurrentPositionOffset!=0,这个方法调用 //加if判断防颤抖 if (mCurrentPositionOffset == 0) { mCurrentIndex = i; invalidate(); } } @Override public void onPageScrollStateChanged(int i) { } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable("instanceState", super.onSaveInstanceState()); bundle.putInt("mCurrentTab", mCurrentIndex); bundle.putInt("mNodeCount", mNodeCount); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; mCurrentIndex = bundle.getInt("mCurrentTab"); mNodeCount = bundle.getInt("mNodeCount"); if (mCurrentIndex >= 0 && mCurrentIndex < mNodeCount) { requestLayout(); } state = bundle.getParcelable("instanceState"); } super.onRestoreInstanceState(state); } /** * 关联ViewPager,用于连适配器都不想自己实例化的情况 */ public void setViewPager(ViewPager vp, FragmentActivity fa, ArrayList fragments) { setViewPager(vp, fa.getSupportFragmentManager(), fragments); } /** * 关联ViewPager,用于连适配器都不想自己实例化的情况 */ public void setViewPager(ViewPager vp, FragmentManager fm, ArrayList fragments) { if (vp == null) { throw new IllegalStateException("ViewPager can not be NULL !"); } this.mViewPager = vp; this.mViewPager.setAdapter(new InnerPagerAdapter(fm, fragments)); this.mViewPager.removeOnPageChangeListener(this); this.mViewPager.addOnPageChangeListener(this); mNodeCount = fragments.size(); requestLayout(); } static class InnerPagerAdapter extends FragmentPagerAdapter { private ArrayList fragments = new ArrayList<>(); public InnerPagerAdapter(FragmentManager fm, ArrayList fragments) { super(fm); this.fragments = fragments; } @Override public int getCount() { return fragments.size(); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁 // super.destroyItem(container, position, object); } @Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; } } protected int dp2px(float dp) { final float scale = mContext.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } protected int sp2px(float sp) { final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; return (int) (sp * scale + 0.5f); }}
更多相关文章
- 意见反馈 页面布局的设计
- ViewPager初步用法(二)
- Android(安卓)SAX解析XML文件
- android Studio listView 简单的用法
- 7.高级UI组件
- 过期Gallery取代方案horizontalscrollView之幻灯片效果
- 自动输入文本效果—AutoCompleteTextView
- 绘制直角坐标系
- android studio自动提示文本框