自定义控件——优雅的指示器Indictor

之前写轮播条或者指示器的时候都是UI图里面直接有,这样的效果并不好,给用户的体验比较差,所以闲暇之余自己写了个指示器,可以展现出一个优雅的效果,当手指 当手指滑动的时候小圆点会跟着一点一点的滑动,当手指停下时,小红点也跟着停下来。原理:在相对布局里面包裹一个线性局,一个展示图片的View,线性布局里面在代码里面动态添加的指示器个数,View布局显示被选中的状态,让这两个子布局重叠,通过监听ViewPager的滑动状态,来改线被选中的View的的位置,以实现滑动状态选中的效果。在代码里面动态控制的具体步骤如下:
1、使用LayParams给布局里面添加未选中的小圆点,例如灰色;
2、设置小红点,表示滑动后的状态。
3、获取小圆点之间的距离,这里要获取小圆点的距离不能简单地getWidth,getHeiget,这样是获取不到的 ,这里要用到视图树来观察两个点距离左侧屏幕之间的距离,然后求差获取距离。
4、在监听viewpager的时候获取两者的距离。

一、布局文件
1、MainActivity布局
<!--小红点,小圆点的滑动,具体布局在代码里面写的-->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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.support.v4.view.ViewPager
        android:id="@+id/vp_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

        <Button
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="60dp"
            android:background="#FFF107"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="20sp"
            android:text="开始体验"
            android:visibility="gone"/>
    
        <!--小红点,小圆点的滑动,具体布局在代码里面写的-->
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="20dp">
        
            <LinearLayout
                android:id="@+id/ll_point_group"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
            </LinearLayout>
        
            <View
                android:id="@+id/view_red_point"
                android:layout_width="10dp"
                android:layout_height="10dp"
                android:background="@drawable/shape_guide_point_selected"/>
        </RelativeLayout>

</RelativeLayout>
2、指示器状态的shape
<!--普通的圆点-->
<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
           android:shape="oval" >
    <solid android:color="@android:color/darker_gray" />
</shape>
<!--小红点的圆点-->
<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
           android:shape="oval" >
    <solid android:color="#f00" />
</shape>
二、MainActivity中代码
1、初始化指示器
    private void initView() {
        int[] icons = {R.mipmap.guide1,R.mipmap.guide2,R.mipmap.guide3,R.mipmap.guide4};
        mList = new ArrayList<>();
        for (int i = 0; i < icons.length; i++) {
            ImageView view = new ImageView(this);
            view.setBackgroundResource(icons[i]); //只有设置了背景才能填充满屏幕
            mList.add(view);

            //设置,灰色的小圆点,表示滑动时候的状态
            View point = new View(this);
            point.setBackgroundResource(R.drawable.shape_guide_point_default); //设置背景
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtils.dp2px(this,10), DensityUtils.dp2px(this,10));
            point.setLayoutParams(params);
            if (i != 0) {
                params.leftMargin = DensityUtils.dp2px(this, 10);
            }
            llpointGroup.addView(point);
        }
    }
2、获取小红点之间的距离
    private void initPoint() {
        // measure -> layout -> draw
        viewRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            //完成布局后回调该方法,该方法有可能被多次回调
            @Override
            public void onGlobalLayout() {
                viewRedPoint.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                mPointWidth = llpointGroup.getChildAt(1).getLeft() - llpointGroup.getChildAt(0).getLeft();
            }
        });
    }
3、让小红点联动,监听ViewPager
    private void initScrollListen() {

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            //当页面被滑动的时候
            //参数一:当前页面的位置 参数二:偏移的百分比 参数三:偏移的距离
            @Override
            public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {
                int leftMargin = (int) (mPointWidth * (position + positionOffset));
                RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) viewRedPoint.getLayoutParams();
                lp.leftMargin = leftMargin;
                viewRedPoint.setLayoutParams(lp);
            }

            //当页面被选择
            @Override
            public void onPageSelected(int position) {

            }

            //当页面状态改变的时候
            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值