老猪带你玩转android自定义控件一——打造最简单viewpagerindicator

  viewpagerindicator,既使用viewpager翻页时候,标题的指示条随着改变的控件,是常用android控件之一,几乎所有的新闻类APP中都有使用。如下图所示:

  今天,我们将从0到1实现这一控件。

  其实,实现这一控件思路很简单:

  ①对头部的标题栏进行布局,头部标题栏,只能进行单选,这符合radiobutton的特质,但是普通的radiobutton,不是这样的吗?

  显然,我们在这里需要写样式进行处理,由于头部标题栏的条目非常的多,一个屏幕放不下,因此我们需要一个水平滚动条来盛放这很多的条目。

  ②我们看到底部的内容随着指示条再不断滑动,因此底部内容是一个viewpager。

  ③下面就是这个控件最关键的部分,就是指示条随着viewpager的内容相互滚动,这涉及到一定逻辑,下面我会阐述这方面的逻辑内容。

  说了一大段开场白以后,我们就应该庖丁解牛般的实现我们控件,废话少说,直接上代码,首先,粉墨登场是头部控件xml布局文件。

  

<!--
  头部标题栏
 包含一个水平滚动条
 单选按钮组
 以及一个标题指示条
 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <HorizontalScrollView
        android:id="@+id/hsv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:fadingEdge="none"
        android:scrollbars="none" >

        <!-- 单选按钮 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <RadioGroup
                android:id="@+id/rg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal" >
            </RadioGroup>

            <FrameLayout
                android:layout_width="fill_parent"
                android:layout_height="2dp" >

                <View
                    android:id="@+id/indicator"
                    android:layout_width="100dp"
                    android:layout_height="2dp"
                    android:background="#ff0000" />
            </FrameLayout>
        </LinearLayout>
    </HorizontalScrollView>

</LinearLayout>

  我们看到这个控件包含一个能够左右滚动水平滚动条,由于每个标题条目就是一个radiobutton,所以需要把这个radio button 放在一个单项按钮组中。当然,还需要一个指示翻到第几页的指示条。

  接下来,就是重头戏了,这个自定义控件逻辑控制。我们看一下他的流程图

  

  通过上述流程图,我们可以得出指示条伴随头部栏与viewpager滑动而滑动。

  做了这么多铺垫,这个控件的核心——逻辑代码将要暴露他的庐山真面目。

  一个自定义控件,首先要初始化原有控件。代码如下:

  

    /**
     * 初始化 相应控件 并且为相应控件赋予相应的事件
     * @param context
     */
    @SuppressLint("InflateParams")
    private void initView(Context context) {

        hsv = (HorizontalScrollView) findViewById(R.id.hsv);

        rg = (RadioGroup) findViewById(R.id.rg);
        rg.setOnCheckedChangeListener(this);
        indicator = findViewById(R.id.indicator);

    }

    /**
     * 为标题条目动态赋值
     */
    public void setDatas(List<String> datas) {
        this.datas = datas;
        addView();
    }

    /**
     * 将标题控件动态添加radiobuttonGroup控件中去
     */
    @SuppressLint("ResourceAsColor")
    private void addView() {
        for (int i = 0; i < datas.size(); i++) {
            RadioButton radioButton = new RadioButton(getContext());
            radioButton.setText(datas.get(i));
            radioButton.setId(10000 + i);
            radioButton.setBackgroundResource(R.color.white);
            radioButton.setButtonDrawable(null);
            radioButton.setButtonDrawable(android.R.color.transparent);
            radioButton.setTextColor(R.color.black);
            LayoutParams layoutParams = new LayoutParams(Dp2Px(getContext(),
                    100), LayoutParams.WRAP_CONTENT);
            radioButton.setLayoutParams(layoutParams);
            radioButton.setGravity(Gravity.CENTER);
            int px = Dp2Px(getContext(), 8);
            radioButton.setPadding(px, px, px, px);

            rg.addView(radioButton);
        }

    }
    

  这里,大伙应当对两个方面的问题引起重视:

  ①我们所说哪些头部标题并不是固定的,是动态生成的,因此显示每个标题radiobutton控件,是随着标题的条目动态添加到父控件中去的。

  ②前文说道,由于每个radiobutton样式非常丑陋,不符合我们的需求,因此我们需要通过相应的代码控制它的样式。

  由于这个控件归根结底是对viewpager翻页效果进行一个指示,怎么能够少得了viewpager对象,相应的源代码如下:

    /**
     * 设置viewpager对象
     */
    public void setPager(ViewPager pager) {
        this.pager = pager;
        setPagerListener();
    }

    /**
     * 对viewpager翻页进行监听
     */
    private void setPagerListener() {
        pager.setOnPageChangeListener(this);
    }    

  其主要就是对于viewpager的翻页效果进行监听。

  怎么使翻页翻到那一页的时候,指示条也随之移动,让我妈老瞅瞅他的代码:

    /**
     * 页面滚动 指示条随之移动 当条目滚出屏幕的时候,水平滚动条也随之移动
     */
    @Override
    public void onPageScrolled(int position, float positionOffset,
            int positionOffsetPixels) {
        int sum = 0;
        sum = (int) ((position+positionOffset)*rg.getChildAt(position).getWidth());

        int green = (pager.getWidth() - rg.getChildAt(position).getWidth()) / 2;
        dx = sum - green;// 计算出要滑出去的距离
        hsv.scrollTo(dx, 0);
        tempx=hsv.getScrollX();
        indicatorScroll(position, positionOffset);

    }

    /**
     * 指示条随着页面的移动也跟随着滑动
     */
    int tempx=0;
    private void indicatorScroll(int position, float positionOffset) {
        RadioButton button = (RadioButton) rg.getChildAt(position);
        int[] location = new int[2];
        button.getLocationInWindow(location);
        // 开始做位移滑动
        TranslateAnimation animation = new TranslateAnimation(fromX,
                location[0] + positionOffset * button.getWidth()+tempx, 0, 0);
        animation.setDuration(50);// 动画持续事件
        animation.setFillAfter(true);
        fromX = (int) (location[0] + button.getWidth() * positionOffset+tempx);
        indicator.startAnimation(animation);// 线开始动画
    }    

  对于这个逻辑,大家应当注意两点:

  第一点,单条目滚出屏幕的时候,我们应当相应条目将其滚动到屏幕中央位置,那么他所需滚动位置,如图所示:

 

 第二点,关于指示条计算就是移动到相应条目位置-水平滚动条滚动的位置。

  这样一个自定义的viewpagerindicator就大功告成了,效果如下:

  

  源代码地址为:

  http://pan.baidu.com/s/1eQ9Fi62

时间: 2024-08-11 14:22:11

老猪带你玩转android自定义控件一——打造最简单viewpagerindicator的相关文章

老猪带你玩转android自定义控件二——自定义索引栏listview

带索引栏的listview,在android开发非常普遍,方便用户进行字母索引,就像微信通讯录这样: 今天,我们就从零到一实现这个具有索引栏的listview. 怎么实现这个控件了,我们应当梳理出一个思路. ①首先应当将字母的索引栏继承与一个控件,通过ondraw方法将字母画出来. ②然后我们应该监听这个字母控件的ontouch事件,来判断用户到底是按了那个字母. ③就是实现这个索引栏与listview的联动,就是将listview滑动到按下字母的位置. 大体流程图如下: 有了前面铺垫,我们引出

老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件

ios 8 的时间滚轮控件实现了扁平化,带来很好用户体验,android没有现成控件,小弟不才,数学与算法知识不过关,顾十分苦恼,幸好在github上找到sai大神实现代码,甚为欣喜,顾把学习这个控件点滴记录下来,分享给大家.项目原地址https://github.com/saiwu-bigkoo/Android-PickerView. ios 8 滚轮的效果: 而sai大神控件的效果: 哎,妈呀是不是效果95%相识啊. 好了,废话少说,谈谈我从这个控件中收获的心得. 首先,我们要高瞻远瞩看一下

玩转android自定义控件二——自定义索引栏listview

带索引栏的listview,在android开发非常普遍,方便用户进行字母索引,就像微信通讯录这样: 今天,我们就从零到一实现这个具有索引栏的listview. 怎么实现这个控件了,我们应当梳理出一个思路. ①首先应当将字母的索引栏继承与一个控件,通过ondraw方法将字母画出来. ②然后我们应该监听这个字母控件的ontouch事件,来判断用户到底是按了那个字母. ③就是实现这个索引栏与listview的联动,就是将listview滑动到按下字母的位置. 大体流程图如下: 有了前面铺垫,我们引出

Android 自定义控件 优雅实现元素间的分割线 (支持3.0以下)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42407923 ,本文出自:[张鸿洋的博客] 1.概述 话说,随着Android SDK版本的升级,很多控件增加了新的属性方便我们的使用,比如LinearLayout中多了:divider.showDividers等,用于为其内部元素添加分隔:但是呢,这样的属性在较低版本的SDK中不能被支持,那么,我们在开发过程中,可能会出现这样的需求:将这个新的特性想办法做到尽可能的向下兼容.

Android SurfaceView实战 打造抽奖转盘

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41722441 ,本文出自:[张鸿洋的博客] 1.概述 今天给大家带来SurfaceView的一个实战案例,话说自定义View也是各种写,一直没有写过SurfaceView,这个玩意是什么东西?什么时候用比较好呢? 可以看到SurfaceView也是继承了View,但是我们并不需要去实现它的draw方法来绘制自己,为什么呢? 因为它和View有一个很大的区别,View在UI线程去

Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

Android 高仿微信6.0主界面 带你玩转切换图标变色

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41087219,本文出自:[张鸿洋的博客] 1.概述 学习Android少不了模仿各种app的界面,自从微信6.0问世以后,就觉得微信切换时那个变色的Tab图标屌屌的,今天我就带大家自定义控件,带你变色变得飞起~~ 好了,下面先看下效果图: 清晰度不太好,大家凑合看~~有木有觉得这个颜色弱爆了了的,,,下面我动动手指给你换个颜色: 有没有这个颜色比较妖一点~~~好了~下面开始介绍

玩转Android Camera开发(五):基于Google自带算法实时检测人脸并绘制人脸框(网络首发,附完整demo)

本文主要介绍使用Google自带的FaceDetectionListener进行人脸检测,并将检测到的人脸用矩形框绘制出来.本文代码基于PlayCameraV1.0.0,在Camera的open和preview流程上进行了改动.原先是放在单独线程里,这次我又把它放到Surfaceview的生命周期里进行打开和开预览. 首先要反省下,去年就推出了静态图片的人脸检测demo,当时许诺一周内推出Camera预览实时检测并绘制的demo,结果拖到现在才整.哎,屌丝一天又一天,蹉跎啊.在demo制作过程中

Android SurfaceView实战 带你玩转flabby bird (下)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43063331,本文出自:[张鸿洋的博客] 1.概述 在Android SurfaceView实战 带你玩转flabby bird (上)中,我们完成了在游戏所需的所有的元素的绘制,包括 Bird鸟. Floor地板.Pipe 管道 .背景图以及分数等. 本篇博客将在上篇的基本上,继续带领大家向我们的目标进发,那么问题来了,我们的目标是: 就是这个效果图了. 首先我们明确下,当然