自定义view,垂直seekbar

来源:互联网 发布:物理模拟实验室软件 编辑:程序博客网 时间:2024/05/05 09:12

话不多说,公司接到的项目中有个效果是上下拉的窗帘,本来是用seekbar旋转90°做的,但是seekbar的属性太多,而且seekbar的滑块会直接显示最底层的颜色(我也不知道为什么), 所有就写了一个自定义view,其实就是一个垂直的seekbar,实现一些简单的操作,例如设置进度,设置前景色和背景色、滑块图片。

首先先看看这个最终效果是什么样的:

然后我们再分析一下这个效果的构成:

1.最底层是白色的。

2.上一层是绿色的(管他什么绿,反正就是绿)。

   3.在上层颜色的底部中间有一个滑块。

分析之后,我们就可以开始考虑怎么写了,下面直接上代码。

<declare-styleable name="WindowBarView">        <!--bgcolor:背景颜色-->        <!--cendiagram:中心原点的图片-->        <!--foreground:前景颜色-->        <!--maxprogress:最大进度-->        <!--nowrogress:当前进度-->        <attr name="bgcolor" format="color" />        <attr name="cendiagram" format="color|reference" />        <attr name="foreground" format="color" />        <attr name="maxprogress" format="integer" />        <attr name="nowrogress" format="integer" />    </declare-styleable>
因为需要给控件设置一些属性,我们就先在attrs文件中加入属性(没有这个文件就先创建一个)。

然后就是java文件了,我们让这个自定义view集成自view,代码是酱婶儿的。

public class WindowBarView extends View {    private int progress = 0;    private int maxprogress = 0;    private int nowrogress = 0;    private int bgcolor = 0;    private int Foreground = 0;     //窗帘下拉的覆盖的颜色    private Paint paint;    private Paint foregrodpaint;    private Drawable cendiagram = null;     //中心圆点的图片    private Bitmap cendiagrambp = null;    // 获得图片的宽高    int widthbm = 0;    int heightbm = 0;    // 取得想要缩放的matrix参数    Matrix matrix;    Bitmap newbm;    private float mPreX, mPreY;    int width, height;    Rect rect;    Rect rectforegroud;    public setonBarTouthnListener touthnListener = null;    public interface setonBarTouthnListener {        public void GetProgress(int progress);    }    public void getonBarProgressListener(setonBarTouthnListener touthnListener) {        this.touthnListener = touthnListener;    }    public WindowBarView(Context context) {        super(context);    }    public WindowBarView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initView(context, attrs);    }    public WindowBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView(context, attrs);    }    public WindowBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        initView(context, attrs);    }    private void initView(Context context, AttributeSet attrs) {        paint = new Paint();        foregrodpaint = new Paint();        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.WindowBarView);        Foreground = array.getInteger(R.styleable.WindowBarView_foreground, Color.WHITE);        cendiagram = array.getDrawable(R.styleable.WindowBarView_cendiagram);        maxprogress = array.getInteger(R.styleable.WindowBarView_maxprogress, 100);        nowrogress = array.getInteger(R.styleable.WindowBarView_nowrogress, 0);        bgcolor = array.getInteger(R.styleable.WindowBarView_bgcolor, Color.WHITE);        setProgress(array.getInteger(R.styleable.WindowBarView_nowrogress, nowrogress));        array.recycle();        cendiagrambp = drawableToBitmap(cendiagram);        // 获得图片的宽高        widthbm = cendiagrambp.getWidth();        heightbm = cendiagrambp.getHeight();        // 设置想要的大小        int newWidth = 100;        int newHeight = 100;        // 计算缩放比例        float scaleWidth = ((float) newWidth) / widthbm;        float scaleHeight = ((float) newHeight) / heightbm;        // 取得想要缩放的matrix参数        matrix = new Matrix();        matrix.postScale(scaleWidth, scaleHeight);        // 得到新的图片        newbm = Bitmap.createBitmap(cendiagrambp, 0,                0, widthbm, heightbm, matrix, true);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int wideSize = MeasureSpec.getSize(widthMeasureSpec);        int wideMode = MeasureSpec.getMode(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        if (wideMode == MeasureSpec.EXACTLY) { //精确值 或matchParent            width = wideSize;        } else {            width = getPaddingLeft() + getPaddingRight();            if (wideMode == MeasureSpec.AT_MOST) {                width = Math.min(width, wideSize);            }        }        if (heightMode == MeasureSpec.EXACTLY) { //精确值 或matchParent            height = heightSize;        } else {            height = getPaddingTop() + getPaddingBottom();            if (heightMode == MeasureSpec.AT_MOST) {                height = Math.min(height, heightSize);            }        }        setMeasuredDimension(width, height);        rect = new Rect(0, 0, width, height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        rectforegroud = new Rect(0, 0, width, (int) mPreY);        paint.setStyle(Paint.Style.FILL);        paint.setColor(bgcolor);        paint.setAntiAlias(true);        canvas.drawRect(rect, paint);        foregrodpaint.setStyle(Paint.Style.FILL);        foregrodpaint.setAntiAlias(true);        foregrodpaint.setColor(Foreground);        canvas.drawRect(rectforegroud, foregrodpaint);        canvas.drawBitmap(newbm, width / 2 - newbm.getWidth() / 2, (int) mPreY - newbm.getHeight() / 2, paint);     //绘制滑块    }    /**     * 获取当前位置     */    public int getProgress() {        if(mPreY==0){            progress = (int) ((float) nowrogress / (float) maxprogress * 100);  //当前进度        }else{            progress = Math.round(mPreY / height*(float) maxprogress);  //当前进度        }        return progress;    }    /**     * 设置当前进度     */    public synchronized void setProgress(final int nowrogress) {        if(height != 0){            mPreY = ((int) ((float) nowrogress / (float) maxprogress * height));            invalidate();        }else{            new Thread() {                @Override                public void run() {                    super.run();                    try {                        Thread.sleep(100);                        if (height != 0) {                            mPreY = ((int) ((float) nowrogress / (float) maxprogress * height));                            postInvalidate();                        }                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }.start();        }    }    /**     * 判断,如果滑动的位置大于控件的高度,说明此事滑块已经滑到下面     * 如果小于0说明在上面     *     * @param event     * @return     */    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mPreX = event.getX();                mPreY = event.getY();                touthnListener.GetProgress((int) (mPreY / height * maxprogress));                invalidate();                return true;            case MotionEvent.ACTION_MOVE:                mPreY = event.getY();                if (mPreY < 0) {                    mPreY = 0;                } else if (mPreY > height) {                    mPreY = height;                } else {                    mPreY = event.getY() + 8;                }                touthnListener.GetProgress((int) (mPreY / height * maxprogress));                invalidate();                break;        }        return super.onTouchEvent(event);    }    /**     * drawable转bitmap     *     * @param drawable     * @return     */    public static Bitmap drawableToBitmap(Drawable drawable) {        Bitmap bitmap = Bitmap.createBitmap(                drawable.getIntrinsicWidth(),                drawable.getIntrinsicHeight(),                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888                        : Bitmap.Config.RGB_565);        Canvas canvas = new Canvas(bitmap);        //canvas.setBitmap(bitmap);        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());        drawable.draw(canvas);        return bitmap;    }}

主要就是onDraw中的内容。

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        rectforegroud = new Rect(0, 0, width, (int) mPreY);        paint.setStyle(Paint.Style.FILL);        paint.setColor(bgcolor);        paint.setAntiAlias(true);        canvas.drawRect(rect, paint);        foregrodpaint.setStyle(Paint.Style.FILL);        foregrodpaint.setAntiAlias(true);        foregrodpaint.setColor(Foreground);        canvas.drawRect(rectforegroud, foregrodpaint);        canvas.drawBitmap(newbm, width / 2 - newbm.getWidth() / 2, (int) mPreY - newbm.getHeight() / 2, paint);     //绘制滑块    }
这个控件我将它分为了三层,这样我就需要在画布上画三次,第一次,绘制最底层颜色,第二次,绘制上一层颜色,第三次绘制滑块,这样才能得到想要的效果。

下面就是使用方法。

<com.tianer.dooya.weight.WindowBarView                    android:id="@+id/timeline"                    android:layout_width="200dp"                    android:layout_height="300dp"                    app:bgcolor="@color/white"                    app:foreground="@color/windowbar"                    app:cendiagram="@drawable/bgg"                    app:maxprogress="100"/>

最后,上个效果图。

上个源码地址

https://github.com/dzghxs/WindowBarView点击打开链接