自定义View(音量条)

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

首先要感谢鸿洋大神的自定义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(音量条),就完成了,效果如图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值