Android UI之自定义头部指示器实现仿网易云音乐地区选择

1. 简介 

本文将记录的是一些有效的自定义指示器demo,诚然Indicator的开源框架还是比较多的,我们在具体具体中可以衡量。一些简单的自定义基础还是有必要好好掌握的。

2. demo样例

2.1 图片背景选择(stateListDrawable)+ViewPager样式

stateListDrawable相关文章:

首先看下效果吧:Android UI之stateListDrawable stateListAnimator ripple背景的综合运用

如下图所示,可以滑动viewPager来滑动头部的指示器;也可以通过点击指示器来选择不同的界面

Android UI之自定义头部指示器实现仿网易云音乐地区选择_第1张图片

具体实现:

首先就是布局咯:和 tabLayout+ViewPager的形式是一样的布局



        

            

            

            

        
        
        
    

单个imageView的指示器背景布局如下:stateListDrawable



    
    
    

activity中的核心代码如下:

    // 设置点击事件 --- 改变之前判断是否被选中了---
    private void setListener() {
        ivGank.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //不然cpu会有损耗
                if (mViewPager.getCurrentItem() != 0) {
                    ivGank.setSelected(true);
                    ivBook.setSelected(false);
                    ivMe.setSelected(false);
                    mViewPager.setCurrentItem(0);
                }
            }
        });

        ivBook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //不然cpu会有损耗
                if (mViewPager.getCurrentItem() != 1) {
                    ivGank.setSelected(false);
                    ivBook.setSelected(true);
                    ivMe.setSelected(false);
                    mViewPager.setCurrentItem(1);
                }
            }
        });

        ivMe.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //不然cpu会有损耗
                if (mViewPager.getCurrentItem() != 2) {
                    ivGank.setSelected(false);
                    ivBook.setSelected(false);
                    ivMe.setSelected(true);
                    mViewPager.setCurrentItem(2);
                }
            }
        });
    }

    private void setViewPager() {
        ArrayList fragments = new ArrayList<>();
        fragments.add(new GankFragment());
        fragments.add(new GankFragment());
        fragments.add(new MeFragment());
        mViewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(),fragments));
        mViewPager.setOffscreenPageLimit(2);
        // 设置viewpage滑动监听 ---- 当滑到某个界面时 标题背景改变
        mViewPager.addOnPageChangeListener(this);
        // 设置默认选中第一个 通过选中的背景设置切换
        ivGank.setSelected(true);
        mViewPager.setCurrentItem(0);
    }

还是很easy的,因为我们接触的项目有可能TabLayout不能满足我们的需求,这时候可以去GitHub上找轮子,也可以自己来定义View,也算是一种积累吧。总之 viewPager这一组件讲真还是特别重要的,有必要好好的学习下。

2.2 RadioGroup样例

可以观察下效果:

Android UI之自定义头部指示器实现仿网易云音乐地区选择_第2张图片

 

    
        
        
    

text_radio_color.xml



    
    

drawable_selector_right.xml



    
    





    
    






    
    

2.3 究极RadiaButton实现仿58同城热门城市选择

首先看下效果吧:

Android UI之自定义头部指示器实现仿网易云音乐地区选择_第3张图片

如上所示,基本和58上的一样。下面将解析具体的绘制。

布局文件如下:

    
        

        

        
    

和前面的案例是相类似的,无非就是 radioGroup+radioButton+stateListDrawable+colorSelector等完成的效果。这里drawable包括color文件我就不给出来了,和前面的案例相类似。值得注意的是,可以发现58案例比简易案例多了边缘框和中间的分割线,这就是不同点,也是需要指出的具体细节,接下来就相应的进行解析。

 编写自定义控件继承自RadioGroup,绘制背景边框,接着再绘制分割线即可。代码如下所示。

public class WubaTownRadioGroup extends RadioGroup
{
    // 边缘 分割线颜色
    private int bgColor = Color.parseColor("#ff552e");
    // 画笔
    private Paint mpaint;
    // 圆弧半径 === 注意这里的半径 应当和xml里设置的左右的corners 呈对应关系
    private int roundWidth;
    // 边缘线宽度
    private int strokeWidth;

    public WubaTownRadioGroup(Context paramContext)
    {
        super(paramContext);
    }

    public WubaTownRadioGroup(Context paramContext, AttributeSet paramAttributeSet)
    {
        super(paramContext, paramAttributeSet);
    }

    private void drawDivider(Canvas paramCanvas)
    {
        if (getOrientation() == LinearLayout.HORIZONTAL)
        {
            int j = getChildCount();
            if (j > 1)
            {
                int i = 1;
                while (i < j)
                {
                    int k = getChildAt(i).getLeft();
                    paramCanvas.drawLine(k, 0.0F, k, getMeasuredHeight(), this.mpaint);
                    i += 1;
                }
            }
        }
    }

    private void drawRoundBackGround(Canvas paramCanvas)
    {
        this.roundWidth = ((int)TypedValue.applyDimension(1, 4.0F, getResources().getDisplayMetrics()));
        float f = this.mpaint.getStrokeWidth() - 1.0F;
        // 绘制圆角矩形
        paramCanvas.drawRoundRect(new RectF(
                0.0F + f,
                0.0F + f,
                getMeasuredWidth() - f,
                getMeasuredHeight() - f),
                this.roundWidth,
                this.roundWidth,
                this.mpaint);
    }
    

    private void initPaint()
    {
        // 这里要做适配
        this.strokeWidth = ((int) TypedValue.applyDimension(1, 1.0F, getResources().getDisplayMetrics()));
        this.mpaint = new Paint();
        this.mpaint.setStrokeWidth(this.strokeWidth);
        // 设置抗锯齿 优化显示效果
        this.mpaint.setAntiAlias(true);
        // 设置防止抖动
        this.mpaint.setDither(true);
        this.mpaint.setStyle(Paint.Style.STROKE);
        this.mpaint.setColor(this.bgColor);
    }

    @Override
    protected void dispatchDraw(Canvas paramCanvas)
    {
        super.dispatchDraw(paramCanvas);
        if ((getMeasuredHeight() > 0) && (getMeasuredWidth() > 0))
        {
            initPaint();
            drawRoundBackGround(paramCanvas);
            drawDivider(paramCanvas);
        }
    }

    public void setBgColor(int paramInt)
    {
        this.bgColor = paramInt;
    }
}

 

你可能感兴趣的:(android,UI)