自定义ViewPagerIndicator

仲孙华奥
2023-12-01

下载地址

我的学习视频地址,一起来学习Android…
http://edu.csdn.net/course/detail/2741/43164?auto_start=1

http://edu.csdn.net/course/detail/2741/43163
代码下载地址:http://download.csdn.net/detail/zhiyuan0932/9564014

创建构造方法及代码初始化

public ViewPagerIndicator(Context context, AttributeSet attrs,
            int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

    }

    public ViewPagerIndicator(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }



    public ViewPagerIndicator(Context context) {
        super(context);
        init();
    }
        private void init() {
        // 获取当前屏幕的宽高
        WindowManager windowManager = (WindowManager) getContext()
                .getSystemService(Context.WINDOW_SERVICE);
        outMetrice = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(outMetrice);
        // 初始化画笔
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);
    }

设置关联的viewPager

/**
     * 设置相关联的viewPager
     * 
     * @param viewPager
     */
    public void setViewPager(final ViewPager viewPager) {
        this.viewPager = viewPager;
        // 对viewPager设置监听事件
        viewPager.setOnPageChangeListener(this);
        // 创建线性布局
        linearLayout = new LinearLayout(getContext());
        // 将线性布局添加到当前自定义的HorizontalScrollView中
        this.addView(linearLayout);
        // 获取viewpager的数据适配器,然后获取数据适配器展示的条目的个数
        int count = viewPager.getAdapter().getCount();
        // 循环遍历
        for (int i = 0; i < count; i++) {
            // 获取当前的title
            String title = (String) viewPager.getAdapter().getPageTitle(i);
            // 有多少个Title,就动态的添加多少个TextView
            final TextView textView = new TextView(getContext());
            // 设置线性布局的布局参数
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            // 设置当前的边距值,默认设置为屏幕宽度的1/5
            marginValue = outMetrice.widthPixels / 5;
            params.setMargins(0, 0, marginValue, 5);
            // 设置TextSize
            textView.setTextSize(textSize);
            // 设置TextView的标题
            textView.setText(title);
            if (i == 0) {
                // 对于初始的textView的颜色
                textView.setTextColor(selectedTextColor);
                // 当textView可见的时候,获取textView的宽度
                textView.getViewTreeObserver().addOnGlobalLayoutListener(
                        new OnGlobalLayoutListener() {

                            @SuppressWarnings("deprecation")
                            @Override
                            public void onGlobalLayout() {
                                // 初始的textView的宽度定义为索引值为0位置处的索引值
                                textViewWidth = textView.getWidth();
                                textView.getViewTreeObserver()
                                        .removeGlobalOnLayoutListener(this);
                                // 当获取到textView的宽度时,重新刷新一下界面
                                postInvalidate();
                            }
                        });
            } else {
                // 设置textView的未选中的默认字体颜色
                textView.setTextColor(unselectedTextColor);
            }
            // 将textView添加到线性布局中
            linearLayout.addView(textView, params);
            // 将textView添加到map集合中
            tvMap.put(textView, i);
            // 对textView设置点击事件的监听
            textView.setOnClickListener(this);
        }
    }

设置相应的监听事件


    @Override
    public void onClick(View v) {
        // 获取当前的map中的textView的索引值,然后设置viewPager跳转到那个界面上
        viewPager.setCurrentItem(tvMap.get(v));
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        // 获取当前状态,对于viewPager的状态,并定义到成员
        this.state = state;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset,
            int positionOffsetPixels) {
        // 计算当前的偏移量,用于绘制顶部的红线或者是图片
        int sumWidth = 0;
        // 循环遍历所有的在该position前的控件,然后计算出当前的位置
        for (int i = 0; i < position; i++) {
            sumWidth = sumWidth + linearLayout.getChildAt(i).getWidth()
                    + marginValue;
        }
        // 获取线性布局中的child,然后获取这个textView的宽度
        View view = linearLayout.getChildAt(position);
        int width = view.getWidth();
        // 在滑动时将这个宽度赋值给在成员定义的textViewWidth,用于绘制指示线的宽度(这样可以做到文字有多长,指示线就有多长)
        textViewWidth = width;
        // 计算出当前指示线的起点位置 偏移的比例*(控件自身宽度+控件的marginRight值)+之前计算出的x坐标
        currentX = positionOffset * (width + marginValue) + sumWidth;
        // 刷新onDraw
        postInvalidate();
    }

    /**
     * @param selectTextColor
     *            选中的字体颜色
     * @param normalTextColor
     *            未选中的字体颜色
     * @param textSize
     *            字体大小
     */
    public void setTextViewAttr(int selectedTextColor, int unselectedTextColor,
            int textSize) {
        this.selectedTextColor = selectedTextColor;
        this.unselectedTextColor = unselectedTextColor;
        this.textSize = textSize;
    }

    @SuppressLint("NewApi")
    @Override
    public void onPageSelected(int position) {
        // 当滑动到某一页时,让该索引值下的textView颜色变成选中的颜色
        for (int i = 0; i < linearLayout.getChildCount(); i++) {
            TextView tv_title = (TextView) linearLayout.getChildAt(i);
            if (position == i) {
                tv_title.setTextColor(selectedTextColor);
            } else {
                tv_title.setTextColor(unselectedTextColor);
            }
        }
    }

绘制指示器

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 如果现实indicator显示,就绘制底部的indicator
        if (isVisible) {
            // 判断要显示的indicator时什么样式,是颜色样式还是图片样式
            if (style == STYLE_COLOR) {
                // 绘制指示线
                canvas.drawLine(currentX, this.getHeight(), currentX
                        + textViewWidth, this.getHeight(), paint);
            } else if (style == STYLE_DRAWABLE) {
                // 设置Bitmap左上右下的位置
                RectF dst = new RectF();
                // 左侧时当前的位置
                dst.left = currentX;
                // 右侧是textView宽度+currentX
                dst.right = currentX + textViewWidth;
                // 底部是HorizontalScrollView的高度
                dst.bottom = this.getHeight();
                // 设置顶部的坐标
                dst.top = this.getHeight() * 4.0f / 5;
                // 绘制图片
                canvas.drawBitmap(bitmap, null, dst, paint);
            }
        }
        if (currentX >= outMetrice.widthPixels / 2
                && state == ViewPager.SCROLL_STATE_DRAGGING) {
            // 设置horizontalScrollView滑动到的位置
            this.scrollTo((int) (currentX - outMetrice.widthPixels / 2), 0);
        } else if (currentX < outMetrice.widthPixels / 2
                && state == ViewPager.SCROLL_STATE_DRAGGING) {
            this.scrollTo(0, 0);
        }
    }

设置自定义指示器效果

    /**
     * 设置指示线或者指示图标显示或隐藏,默认显示
     * 
     * @param isVisible
     *            true代表显示,false代表隐藏
     */
    public void setIndicatorVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }

    /**
     * 设置指示器类型
     * 
     * @param VIEWSTYLE_COLOR
     *            单纯的设置指示器颜色
     * @param STYLE_DRAWABLE
     *            可以设置指示器的图标
     */
    public void setIndicatorStyle(int style) {
        this.style = style;
    }

    /**
     * 设置指示线的颜色
     * 
     * @param indicatorColor
     */
    public void setIndicatorColor(int indicatorColor) {
        paint.setColor(indicatorColor);
    }

    /**
     * 设置指示线的宽度
     * 
     * @param indicatorStrokeWidth
     */
    public void setIndicatorStrokeWidth(int indicatorStrokeWidth) {
        paint.setStrokeWidth(indicatorStrokeWidth);
    }

    /**
     * 如果indicator展示样式为自定义的图片,需要设置图片,否则不需要设置
     * 
     * @param drawableResource
     *            图片资源
     */
    public void setIndicatorResource(int drawableResource) {
        try {
            bitmap = BitmapFactory.decodeResource(getResources(),
                    drawableResource);
            if (bitmap == null) {
                bitmap = BitmapFactory.decodeResource(getResources(),
                        R.drawable.error_tip_btn_pressed);
            }
        } catch (Exception e) {
            Log.i(TAG, "请设置正确图片");
            e.printStackTrace();
        }
    }
    /**
     * @param selectTextColor
     *            选中的字体颜色
     * @param normalTextColor
     *            未选中的字体颜色
     * @param textSize
     *            字体大小
     */
    public void setTextViewAttr(int selectedTextColor, int unselectedTextColor,
            int textSize) {
        this.selectedTextColor = selectedTextColor;
        this.unselectedTextColor = unselectedTextColor;
        this.textSize = textSize;
    }

Xml中引用该ViewPagerIndicator

<LinearLayout 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"
    android:orientation="vertical" >

    <com.zhiyuan.viewpagerindicator.ViewPagerIndicator
        android:id="@+id/chsv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0000"
        android:scrollbars="none" />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

在代码中可以对ViewPagerIndcator进行设置

public class MainActivity extends FragmentActivity {

    private ViewPagerIndicator chsv;
    private ViewPager viewPager;
    String[] titles = new String[] { "AAAAAA", "BBBBBB", "CCCCCC", "DDDDD",
            "EEEE", "FFFF", "G", "H", "III", "GGG", "KKKKKK" };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 关联布局,实例化控件
        chsv = (ViewPagerIndicator) findViewById(R.id.chsv);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPager.setAdapter(new FragmentPagerAdapter(
                getSupportFragmentManager()) {

            @Override
            public int getCount() {
                return titles.length;
            }

            @Override
            public Fragment getItem(int position) {
                Fragment instance = TitleFragment.getInstance(titles[position]);
                return instance;
            }

            /**
             * 设置indicator展示的标题
             */
            @Override
            public CharSequence getPageTitle(int position) {
                return titles[position];
            }
        });
        // viewPager和viewPagerIndicator相关联
        chsv.setViewPager(viewPager);
        // 设置TextView属性
        chsv.setTextViewAttr(Color.WHITE, Color.BLACK, 30);
        // 设置指示器颜色
        chsv.setIndicatorColor(Color.GRAY);
        // 设置是否显示指示器
        chsv.setIndicatorVisible(true);
        // 设置指示器是显示自定义图片还是颜色
        chsv.setIndicatorStyle(ViewPagerIndicator.STYLE_DRAWABLE);
        // 设置指示器显示的图片
        chsv.setIndicatorResource(R.drawable.error_tip_btn_pressed);

    }

}

自己定义的Fragment展示ViewPager内容

public class TitleFragment extends Fragment {
    @SuppressLint("NewApi")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Bundle arguments = getArguments();
        String string = arguments.getString("title", "");
        TextView tv = new TextView(getActivity());
        tv.setText(string);
        return tv;
    }

    /**
     * 获取Fragment实例对象
     * 
     * @param title
     *            当前页面展示的内容
     * @return Fragment
     */
    public static Fragment getInstance(String title) {
        TitleFragment titleFragment = new TitleFragment();
        Bundle args = new Bundle();
        args.putString("title", title);
        titleFragment.setArguments(args);
        return titleFragment;
    }
}
 类似资料: