抽屉侧滑的角标,菜单图片与返回图片的转换

4 篇文章 0 订阅
3 篇文章 0 订阅

我们用的都是系统自己的专用于标题懒得不能单独使用,我就自己定义了一个类似的控件。做的不是很好希望大家多多交流,有问题的可以提出。

下面上传效果图

上面的菜单键变化为两种,一种是拖动的转变,还有就是点击的转变。

下面看一下分析图

1.由菜单键到返回键转变,以180度为周期。旋转中心为中线中心点,主要变化的地方是:

       a.在一个周期内时,绿点向黄点靠拢,

       b.灰点向紫色的点靠拢。这里的向紫色点靠拢实现了箭头两翼线段的缩短,和与中线的夹角为45度。

2.要想实现实时的过程,那我们就要引入一个变量角度值,一个周期180度,我们把上面的靠拢值除以180,再乘以一个变化的角度值就ok了。

3.两侧与中线夹角为45度,为我们计算紫色点的位置提供了帮助。箭头顶点和紫色点到旋转中心距离等同。

4.已知的虚线起点和终点位置以及中心点,基本就搞定了。

5.动画的过程用线程完成。拖动的过程就可以设置角度完成。

6.注意这里线程里面要使用postInvalidate();来做异步处理,invalidate();时做同步处理的,只能用在主UI线程。

下面上代码

public class back_View extends View {
    private int width;
    private int height;
    private float space;
    private float marginLeftAndRight = 10;//左右边距

    private float angle;//旋转角度
    private float cx;//箭头结束点的x轴坐标
    private float cy;//箭头结束点的y轴坐标
    private float lineW;//中线的长度
    //旋转180度后由菜单键变成返回键,因此收尾调转
    private float count;//箭头顶点(中线的终点)到上下两条线终点的就离分成180份,每份代表旋转1度,上下两线的起点向中线终点靠拢的距离y的值
    //箭头两翼末端到中线垂直距离(cy - space * 2),分成180份来移动
    private float px;//(相对位置)当前两翼末端移动的距离,需要在原来两翼末端x轴数值做运算
    private float py;//

    /*设置,绘制的左右边距*/
    public void setMarginLeftAndRight(float marginLeftAndRight) {
        this.marginLeftAndRight = marginLeftAndRight;
    }

    public back_View(Context context) {
        super(context);
    }

    public back_View(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public back_View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = right - left;
        height = bottom - top;
        space = (float) (height / 6.0);
        lineW = width;
        cx = lineW / 2;
        cy = space * 3 - cx + marginLeftAndRight;
//        Log.e("1111", "=========" + width);
        invalidate();
    }

    //获取画笔类
    private Paint getPaint() {
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(6);
        return paint;
    }

    public void click() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (width > 0) {
                    if (angle >= 180) {
                        form180To360();
                    } else if (angle <= 0) {
                        form0To180();
                    }
                }
            }
        }).start();

    }

    /*从0到180度*/
    public void form0To180() {
        while (true) {
            angle++;
            count += (space / 180);
            px += (cx - marginLeftAndRight) / 180;
            py += (cy - space * 2) / 180;
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            postInvalidate();
            if (angle >= 180) {
                angle = 180;
                break;
            }
        }
    }

    /*从180返回0度*/
    public void form180To0() {
        while (true) {
            angle--;
            count -= (space / 180);
            px -= (cx - marginLeftAndRight) / 180;
            py -= (cy - space * 2) / 180;
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            postInvalidate();
            if (angle <= 0) {
                angle = 0;
                break;
            }
        }
    }

    /*从180返回360度*/
    public void form180To360() {
        while (true) {
            angle++;
            count -= (space / 180);
            px -= (cx - marginLeftAndRight) / 180;
            py -= (cy - space * 2) / 180;
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            postInvalidate();
            if (angle >= 360) {
                angle = 0;
                break;
            }
        }
    }

    /*设置旋转角度*/
    public void setAngle(float angle_) {
        angle = angle_;
        count = (space / 180) * angle;
        px = (cx - marginLeftAndRight) / 180 * angle;
        py = (cy - space * 2) / 180 * angle;
        invalidate();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.rotate(angle, cx, (space * 3));//旋转中心
        //上
        canvas.drawLine(px + marginLeftAndRight, space * 2 + py, lineW - marginLeftAndRight, space * 2 + count, getPaint());
        //中线
        canvas.drawLine(0 + marginLeftAndRight, (float) (space * 3), lineW - marginLeftAndRight, (float) (space * 3), getPaint());
        //下
        canvas.drawLine(px + marginLeftAndRight, space * 4 - py, lineW - marginLeftAndRight, (float) (space * 4 - count), getPaint());

    }
}

效果图

activity部分,布局就一个上面自定义控件引用,和一个SeekBar控件。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        view = findViewById(R.id.back_v);
        seekBar = findViewById(R.id.seekBar);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                view.click();
            }
        });
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                view.setAngle((float) (1.8 * progress));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值