美文网首页
笔记20170530--自定义一个显示步骤的View(andro

笔记20170530--自定义一个显示步骤的View(andro

作者: hello我的world | 来源:发表于2017-05-30 15:55 被阅读0次

    需求:

    进行到某一步时的步骤提示view(这个笔记主要记录用自定义view的方式完成)

    要达到的效果

    demo.png

    就是根据步骤,相应的字和背景条变颜色

    相关代码:

    attrs.xml属性配置:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <attr name="numberTextOne" format="string"/>
        <attr name="numberTextTwo" format="string"/>
        <attr name="numberTextThree" format="string"/>
    
        <attr name="bottomTextOne" format="string"/>
        <attr name="bottomTextTwo" format="string"/>
        <attr name="bottomTextThree" format="string"/>
        <attr name="bottomTextSize" format="dimension"/>
        <attr name="bgSelectColor" format="color"/>
        <attr name="bgUnSelectColor" format="color"/>
        
        <declare-styleable name="NextView">
            <attr name="numberTextOne"/>
            <attr name="numberTextTwo"/>
            <attr name="numberTextThree"/>
            <attr name="bottomTextOne"/>
            <attr name="bottomTextTwo"/>
            <attr name="bottomTextThree"/>
            <attr name="bottomTextSize"/>
            <attr name="bgSelectColor"/>
            <attr name="bgUnSelectColor"/>
        </declare-styleable>
    </resources>
    
    NextView代码:
    package w.k.w.demonextview;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.support.v4.content.ContextCompat;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * Created by Hello我的World on 2017/5/29.
     */
    
    public class NextView extends View {
    
        private String numberTextOne;//第一步圆圈的数字
        private String numberTextTwo;//第二步圆圈的数字
        private String numberTextThree;//第三步圆圈的数字
        private String bottomTextOne;//第一步圆圈下边的数字
        private String bottomTextThree;//第二步圆圈下边的数字
        private String bottomTextTwo;//第三步圆圈下边的数字
        private float bottomTextSize;//圆圈下边数字的大小
        private int bgSelectColor;//完成时的颜色
        private int bgUnSelectColor;//未完成时的颜色
    
        private Paint paint; //画笔
        private Rect numTextRect;//绘制文字时背景的框
        private float sCircleX;//第二个圆的x坐标
        private float sCircleY;//第二个圆的y坐标
        private float fCircleX;//第一个圆的x坐标
        private float fCircleY;//第一个圆的y坐标
        private float lCircleX;//最后一个圆的x坐标
        private float lCircleY;//最后一个圆的y坐标
        private float circleRadius;//圆的半径
        private RectF fistLine;//第一个用作当线的矩形
        private RectF secondLine;//第二个用作当线的矩形
        private RectF thirdLine;//第三个用做当线的矩形
        private RectF lastLine;//最后一个用做当线的矩形
    
        private int stepIndex;//步骤的下标
    
        public NextView(Context context) {
            this(context, null);
        }
    
        public NextView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public NextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //获取属性
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NextView, defStyleAttr, 0);
    
            int n = a.getIndexCount();
            for(int i=0;i<n;i++){
                int attr = a.getIndex(i);
                switch (attr){
                    case R.styleable.NextView_numberTextOne:
                        numberTextOne = a.getString(attr);
                        break;
                    case R.styleable.NextView_numberTextTwo:
                        numberTextTwo = a.getString(attr);
                        break;
                    case R.styleable.NextView_numberTextThree:
                        numberTextThree = a.getString(attr);
                        break;
                    case R.styleable.NextView_bottomTextOne:
                        bottomTextOne = a.getString(attr);
                        break;
                    case R.styleable.NextView_bottomTextTwo:
                        bottomTextTwo = a.getString(attr);
                        break;
                    case R.styleable.NextView_bottomTextThree:
                        bottomTextThree = a.getString(attr);
                        break;
                    case R.styleable.NextView_bottomTextSize:
                        bottomTextSize = a.getDimension(attr,1);
                        break;
                    case R.styleable.NextView_bgSelectColor:
                        bgSelectColor = a.getColor(attr, ContextCompat.getColor(context,R.color.colorPrimary));
                        break;
                    case R.styleable.NextView_bgUnSelectColor:
                        bgUnSelectColor = a.getColor(attr,ContextCompat.getColor(context,R.color.colorAccent));
                        break;
                }
            }
            a.recycle();
            //初始化画笔和当作字背景的矩形
            paint = new Paint();
            numTextRect= new Rect();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            //设置不透明,抗锯齿
            paint.setAlpha(255);
            paint.setAntiAlias(true);
            //圆的半径为宽度的25分之1
            circleRadius = getWidth()/25;
            
            //先画最中间的圆,以它为中心点,往两边扩散着画
            //如果步骤标记小于2,就代表没有到第二步,那么这一步的背景色就是没选中时的颜色
            //第二个圆的中心点应该是控件的最中心,所以x坐标是宽度除以2,y坐标是高度除以2
            if(stepIndex<2){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            sCircleX = getWidth()/2;
            sCircleY = getHeight()/2;
            canvas.drawCircle(sCircleX,sCircleY,circleRadius,paint);
            
            //画第一个圆,背景色逻辑同上
            if(stepIndex<1){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            fCircleX = sCircleX-(getWidth()/4);
            fCircleY = sCircleY;
            canvas.drawCircle(fCircleX,fCircleY,circleRadius,paint);
            
            //画第三个圆,背景色处理同上
            if(stepIndex<3){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            lCircleX = sCircleX+(getWidth()/4);
            lCircleY = sCircleY;
            canvas.drawCircle(lCircleX,lCircleY,circleRadius,paint);
            
            //开始画在圆上的字,字体颜色是白色
            paint.setColor(Color.WHITE);
            paint.setTextSize(30);
            paint.getTextBounds(numberTextTwo, 0, numberTextTwo.length(), numTextRect);
            canvas.drawText(numberTextTwo,sCircleX-(numTextRect.width()/2),sCircleY+numTextRect.height()/2,paint);
    
            paint.getTextBounds(numberTextOne,0,numberTextOne.length(),numTextRect);
            canvas.drawText(numberTextOne,fCircleX-numTextRect.width(),sCircleY+numTextRect.height()/2,paint);
    
            paint.getTextBounds(numberTextThree,0,numberTextThree.length(),numTextRect);
            canvas.drawText(numberTextThree,lCircleX-numTextRect.width()/2,sCircleY+numTextRect.height()/2,paint);
            
            //画线,背景色处理同上
            if(stepIndex<1){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            paint.setStyle(Paint.Style.FILL);
            //第一条线,left左边离控件左边20起,粗细为10,top就是中线-5,right是第一个圆的左侧,bottom是中线-10,下边几条线以此类推
            //需要注意的是,第二条和第三条线的左边起点得是前边圆心减去半径,如果不是步骤不一致时,线的颜色和圆的颜色不一样,就会遮住一部分圆
            fistLine = new RectF(20,sCircleY-5,fCircleX-numTextRect.width(),sCircleY+5);
            canvas.drawRoundRect(fistLine,10,10,paint);
    
            if(stepIndex<2){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            secondLine = new RectF(fCircleX+circleRadius,sCircleY-5,sCircleX-numTextRect.width(),sCircleY+5);
            canvas.drawRect(secondLine,paint);
    
            if(stepIndex<3){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            thirdLine = new RectF(sCircleX+circleRadius,sCircleY-5,lCircleX-numTextRect.width(),sCircleY+5);
            canvas.drawRect(thirdLine,paint);
    
            lastLine = new RectF(lCircleX+numTextRect.width(),sCircleY-5,getWidth()-20,sCircleY+5);
            canvas.drawRoundRect(lastLine,10,10,paint);
            //开始画圆圈下边的字,颜色处理逻辑同上
            if(stepIndex<1){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            paint.setTextSize(bottomTextSize);
            paint.getTextBounds(bottomTextOne,0,bottomTextOne.length(),numTextRect);
            canvas.drawText(bottomTextOne,fCircleX-numTextRect.width()/2,sCircleY+numTextRect.height()*2+10,paint);
    
            if(stepIndex<2){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            paint.getTextBounds(bottomTextTwo,0,bottomTextTwo.length(),numTextRect);
            canvas.drawText(bottomTextTwo,sCircleX-numTextRect.width()/2,sCircleY+numTextRect.height()*2+10,paint);
    
            if(stepIndex<3){
                paint.setColor(bgUnSelectColor);
            }else{
                paint.setColor(bgSelectColor);
            }
            paint.getTextBounds(bottomTextThree,0,bottomTextThree.length(),numTextRect);
            canvas.drawText(bottomTextThree,lCircleX-numTextRect.width()/2,sCircleY+numTextRect.height()*2+10,paint);
        }
    
        public void setStepColor(int stepIndex){
            this.stepIndex = stepIndex;
            invalidate();
        }
    }
    
    
    activity_main.xml:
    <?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"
        xmlns:wkw="http://schemas.android.com/apk/res-auto"
        tools:context="w.k.w.demonextview.MainActivity">
    
        <w.k.w.demonextview.NextView
            android:id="@+id/nextView"
            wkw:bgSelectColor="@color/colorPrimary"
            wkw:bgUnSelectColor="@color/colorAccent"
            wkw:numberTextTwo="2"
            wkw:numberTextOne="1"
            wkw:numberTextThree="3"
            wkw:bottomTextOne="第一步"
            wkw:bottomTextTwo="第二步"
            wkw:bottomTextThree="第三步"
            wkw:bottomTextSize="16sp"
            android:layout_width="match_parent"
            android:layout_height="100dp" />
    
        <Button
            android:layout_below="@id/nextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="第一步"
            android:layout_marginLeft="10dp"
            android:layout_alignParentLeft="true"
            android:id="@+id/firstButton"/>
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/nextView"
            android:layout_centerHorizontal="true"
            android:text="第二步"
            android:id="@+id/secondButton"/>
    
        <Button
            android:layout_below="@id/nextView"
            android:text="第三步"
            android:layout_marginRight="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/lastButton"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    
    MainActivity.java:
    package w.k.w.demonextview;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        NextView nextView;
        Button firstButton,secondButton,lastButton;
        ButtonOnClickListener listener;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            nextView = (NextView) findViewById(R.id.nextView);
            firstButton = (Button) findViewById(R.id.firstButton);
            secondButton = (Button) findViewById(R.id.secondButton);
            lastButton = (Button) findViewById(R.id.lastButton);
            listener = new ButtonOnClickListener();
            firstButton.setOnClickListener(listener);
            secondButton.setOnClickListener(listener);
            lastButton.setOnClickListener(listener);
        }
    
        class ButtonOnClickListener implements View.OnClickListener{
    
            @Override
            public void onClick(View v) {
                switch (v.getId()){
                    case R.id.firstButton:
                        nextView.setStepColor(1);
                        break;
                    case R.id.secondButton:
                        nextView.setStepColor(2);
                        break;
                    case R.id.lastButton:
                        nextView.setStepColor(3);
                        break;
                }
            }
        }
    }
    
    

    实现思路:

    • 想清楚必要条件,3个圆圈,圆圈上有字,四根线,每个圆圈下边有字
    • 将必要条件都写到attrs.xml里:第一个圆圈里的数字,第二个圆圈里的数字,第三个圆圈里的数字,第一个圆圈下边的字,第二个圆圈下边的字,第三个圆圈下边的字,圆圈下边字的大小,选中这一步时的背景色,未选中时的背景色
    • 自定义view,attrs里的属性每个要对应一个变量,然后其他相关变量
    • 构造方法中,获取属性并初始化画笔和当作字背景的矩形对象
    • onDraw方法中先画中间的圆圈,然后根据中间的圆圈画其他的东西
    • setStepColor方法,参数是步骤下标,每次执行此方法时重绘
    • 在Activity中调用此View即可

    BTW:此笔记里的NextView不支持wrap_content

    相关文章

      网友评论

          本文标题:笔记20170530--自定义一个显示步骤的View(andro

          本文链接:https://www.haomeiwen.com/subject/lwjrfxtx.html