自定义View(音量条)

来源:互联网 发布:网络销售客服工作内容 编辑:程序博客网 时间:2024/06/05 17:00

初来乍到,写点东西,方便自己以后用

首先要感谢鸿洋大神的自定义view攻略

自定义view分成几个部分,我自己选择的是顺序是:1view属性确定;2创建view并在构造方法中获取到属性;3重写onDraw; 4重写onMeasure;

View属性确定:

res/values中创建attr文件,里面写明的是自己需要填写的属性

<?xml version="1.0" encoding="utf-8"?><resources>    <attr name="bgColor" format="color"></attr>    <attr name="itemPadding" format="dimension"></attr>    <attr name="unPic" format="reference"></attr>    <attr name="inPic" format="reference"></attr>    <attr name="needNum" format="integer"></attr>    <declare-styleable name="PersonalView">        <attr name="bgColor"></attr>        <attr name="itemPadding"></attr>        <attr name="unPic"></attr>        <attr name="inPic"></attr>        <attr name="needNum"></attr>    </declare-styleable></resources>
可以从代码中看到,其中name为属性名,format为属性所需的值(其中dimesion为尺寸值如dp、sp,reference指的是指定值,例如R.drawable.****,其余的可以百度)

declare-styleable name 为自定义view的名称

然后我们在需要所在的activity的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:app="http://schemas.android.com/apk/res-auto"    tools:context="com.example.administrator.gasprogress.MainActivity">        <com.example.administrator.gasprogress.PersonalView        android:id="@+id/pView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:bgColor="@color/white"        app:itemPadding="7dp"        app:unPic="@drawable/ic_gray"        app:inPic="@drawable/ic_yellow"        app:needNum="15"        android:layout_centerInParent="true"        />    </RelativeLayout>

view构造方法

public class PersonalView extends View {    private int mBgColor;    private int mPadding;    private Drawable mUnBg;    private Drawable mInBg;    private int mNum;    private Paint mPaint;    private Rect mBound;    private int LeastGas;    public int getLeastGas() {        return LeastGas;    }    public void setLeastGas(int leastGas) {        LeastGas = leastGas;    }    public PersonalView(Context context) {        this(context,null);    }    public PersonalView(Context context,  AttributeSet attrs) {        this(context, attrs,0);    }    public PersonalView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.PersonalView,defStyleAttr,0);        int n = a.getIndexCount();        for(int i = 0;i<n;i++){            int attr = a.getIndex(i);            switch (attr){                case R.styleable.PersonalView_bgColor:                    mBgColor = a.getColor(attr, Color.BLACK);                    break;                case R.styleable.PersonalView_itemPadding:                    mPadding = a.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()));                    break;                case R.styleable.PersonalView_unPic:                    mUnBg = a.getDrawable(attr);                    break;                case R.styleable.PersonalView_inPic:                    mInBg = a.getDrawable(attr);                    break;                case R.styleable.PersonalView_needNum:                    mNum = a.getInt(attr,5);                    break;            }        }        a.recycle();        mPaint = new Paint();        mBound = new Rect();    }


如上述代码中,创建了我们自定义view的构造器,并在构造器中,获取了相应的属性值,view的3个构造参数,第一个Context就不多说了,第二个参数AttributeSet
,这个参数就是在xml中获取的数值的调用,我个人理解就是,xml中付的值将通过这个参数在这里返还个自定义view,并使其可以调用,第三个参数defStyleAttr,这个
是一个默认的style,一般不会调用,具体大家可以自行百度。
重写OnDraw()
@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mPaint.setColor(mBgColor);        BitmapDrawable bgB = (BitmapDrawable)mUnBg;        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);//        for(int x = 0;x<mNum;x++){            canvas.drawBitmap(bgB.getBitmap(),0+x*(bgB.getBitmap().getWidth()+mPadding),getHeight()/2-bgB.getBitmap().getHeight()/2,null);        }        BitmapDrawable fb = (BitmapDrawable)mInBg;        canvas.saveLayer(0,0,0,0,null,Canvas.FULL_COLOR_LAYER_SAVE_FLAG);        for(int x = 0;x <getLeastGas(); x++){            canvas.drawBitmap(fb.getBitmap(),0+x*(fb.getBitmap().getWidth()+mPadding),getHeight()/2-fb.getBitmap().getHeight()/2,null);        }        canvas.restore();    }
我这里是做一个类似音量条的一个view,所以其中主要是需要两个图层(因为是最基版,所以并没有加入拖动功能,也没有考虑特别全面,以后应该会完善),这里说明一下
canvas如果要创建一个新图层,需要用到saveLayer这个方法,通过创建新图层,然后再还原最初图层,就可以得到一个覆盖的效果
重写onMeasure()
@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        BitmapDrawable bit = (BitmapDrawable)mUnBg;        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int width;        int height;        if(widthMode == MeasureSpec.EXACTLY){            width = widthSize;        }else {            width = (bit.getBitmap().getWidth()+mPadding)*mNum-mPadding;        }        if(heightMode == MeasureSpec.EXACTLY){            height = heightSize;        }else {            height = bit.getBitmap().getHeight();        }        setMeasuredDimension(width, height);    }

EXACTLY:一般是设置了明确的值或者是MATCH_PARENT

AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT

UNSPECIFIED:表示子布局想要多大就多大,很少使用


就这样一个很基本的自定view(音量条),就完成了,效果如图