android自定义View之(三)------视频音量调控样例

来源:互联网 发布:linux mmap fd 编辑:程序博客网 时间:2024/05/16 11:53

    通过android自定义View之(一)------基本篇,我们学习了如何画一些基本的图形,android自定义View之(二)------简单进度条显示样例篇,我们明白了如何自定义一个view。这个文章,我打算参考《Android 自定义View (四) 视频音量调控》,明白一个音量调控控件是如何实现的。

    1.onMeasure方法的说明:

    在做这个之前,我们还要讲一个自定义view中的重要的一个方法(onMeasure)方法:

   默认onMeasure方法:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)      {          super.onMeasure(widthMeasureSpec, heightMeasureSpec);      }  

    当我们阅读《Android 自定义View (一)》和《Android 自定义View (二) 进阶》,我们会知道在重写onMeasure方法时,对于view的高和宽有三种情况:match_parent, wrap_content,xxx(详细值)。这对应了MeasureSpec的specMode三种类型:

EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST
:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED
:表示子布局想要多大就多大,很少使用

     当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMeasure方法”。

    重写onMeasure方法,有几个方法比较重要:参考下面的方法,我们可以

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  {      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;      }

   确定view的宽和高:

 setMeasuredDimension(width, height);  


2.postInvalidate()和invalidate()

      view的更新界面有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。


3.视频音量调控样例

3.1 效果图



3.2  \res\values\attrs_custom_volum_control_bar.xml

<resources><attr name="firstColor" format="color" /><attr name="secondColor" format="color" /><attr name="circleWidth" format="dimension" /><attr name="dotCount" format="integer" /><attr name="currentCount" format="integer" /><attr name="splitSize" format="integer" /><attr name="bg" format="reference"></attr><declare-styleable name="CustomVolumControlBar">    <attr name="firstColor" />    <attr name="secondColor" />    <attr name="circleWidth" />    <attr name="dotCount" />    <attr name="currentCount" />    <attr name="splitSize" />    <attr name="bg" /></declare-styleable></resources>

3.3 CustomVolumControlBar.java

package com.example.administrator.customview.customview03;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.MotionEvent;import android.view.View;import com.example.administrator.customview.R;public class CustomVolumControlBar extends View {    public static final String TAG = "CustomVolumControlBar";    private int mFirstColor;    private int mSecondColor;    private int mCircleWidth;    private int mCount;    private int mCurrentCount;    private int mSplitSize;    private Bitmap mImage;    private Paint mPaint;    private Rect mRect;    private int xDown, xUp;    public CustomVolumControlBar(Context context) {        super(context);        init(null, 0);    }    public CustomVolumControlBar(Context context, AttributeSet attrs) {        super(context, attrs);        init(attrs, 0);    }    public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(attrs, defStyle);    }    private void init(AttributeSet attrs, int defStyle) {        // Load attributes        final TypedArray a = getContext().obtainStyledAttributes(                attrs, R.styleable.CustomVolumControlBar, defStyle, 0);        int n = a.getIndexCount();        for (int i = 0; i < n; i++)        {            int attr = a.getIndex(i);            switch (attr)            {                case R.styleable.CustomVolumControlBar_firstColor:                    mFirstColor = a.getColor(attr, Color.GREEN);                    break;                case R.styleable.CustomVolumControlBar_secondColor:                    mSecondColor = a.getColor(attr, Color.CYAN);                    break;                case R.styleable.CustomVolumControlBar_bg:                    mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));                    break;                case R.styleable.CustomVolumControlBar_circleWidth:                    mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(                            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));                    break;                case R.styleable.CustomVolumControlBar_dotCount:                    mCount = a.getInt(attr, 10);                    break;                case R.styleable.CustomVolumControlBar_currentCount:                    mCurrentCount = a.getInt(attr, 5);                    break;                case R.styleable.CustomVolumControlBar_splitSize:                    mSplitSize = a.getInt(attr, 20);                    break;            }        }        a.recycle();        mPaint = new Paint();        mRect = new Rect();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mPaint.setAntiAlias(true);        mPaint.setStrokeWidth(mCircleWidth);        mPaint.setStrokeCap(Paint.Cap.ROUND);        mPaint.setAntiAlias(true);        mPaint.setStyle(Paint.Style.STROKE);        int centre = getWidth() / 2;        int radius = centre - mCircleWidth / 2;        drawOval(canvas, centre, radius);        int relRadius = radius - mCircleWidth / 2;        mRect.left = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;        mRect.top = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;        mRect.bottom = (int) (mRect.left + Math.sqrt(2) * relRadius);        mRect.right = (int) (mRect.left + Math.sqrt(2) * relRadius);        if (mImage.getWidth() < Math.sqrt(2) * relRadius)        {            mRect.left = (int) (mRect.left + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getWidth() * 1.0f / 2);            mRect.top = (int) (mRect.top + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getHeight() * 1.0f / 2);            mRect.right = (int) (mRect.left + mImage.getWidth());            mRect.bottom = (int) (mRect.top + mImage.getHeight());        }        canvas.drawBitmap(mImage, null, mRect, mPaint);    }    private void drawOval(Canvas canvas, int centre, int radius) {        float itemSize = (360 * 1.0f - mCount * mSplitSize) / mCount;        RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);        mPaint.setColor(mFirstColor);        for (int i = 0; i < mCount; i++)        {            canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint);        }        mPaint.setColor(mSecondColor);        for (int i = 0; i < mCurrentCount; i++)        {            canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint);        }    }    @Override    public boolean onTouchEvent(MotionEvent event)    {        switch (event.getAction())        {            case MotionEvent.ACTION_DOWN:                xDown = (int) event.getY();                break;            case MotionEvent.ACTION_UP:                xUp = (int) event.getY();                if (xUp > xDown)                {                    down();                } else                {                    up();                }                break;        }        return true;    }    public void up()    {        if(mCurrentCount < mCount){            mCurrentCount++;            postInvalidate();        }    }    public void down()    {        if(mCurrentCount > 0){            mCurrentCount--;            postInvalidate();        }    }    public int getCurrentCount() {        return mCurrentCount;    }    public void setCurrentCount(int mCurrentCount) {        if(mCurrentCount > this.mCount){            this.mCurrentCount = mCount;        }else if(mCurrentCount < 0){            this.mCurrentCount = 0;        }else{            this.mCurrentCount = mCurrentCount;        }        postInvalidate();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }}

3.4 \res\layout\activity_custom_view_activity3.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_height="match_parent"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin"    tools:context="com.example.administrator.customview.customview03.CustomViewActivity3">    <com.example.administrator.customview.customview03.CustomVolumControlBar        android:id="@+id/customVolumControlBar01"        android:layout_width="150dp"        android:layout_height="150dp"        android:layout_centerHorizontal="true"        android:background="#4b4534"        app:firstColor="#fbfbfb"        app:secondColor="#22211a"        app:circleWidth="20dp"        app:dotCount="10"        app:currentCount="6"        app:splitSize="40"        app:bg="@drawable/ic_lock_ringer_on"        />    <com.example.administrator.customview.customview03.CustomVolumControlBar        android:id="@+id/customVolumControlBar02"        android:layout_width="60dp"        android:layout_height="60dp"        android:layout_marginTop="20dp"        android:layout_centerHorizontal="true"        android:layout_below="@+id/customVolumControlBar01"        android:background="#4b4534"        app:firstColor="#fbfbfb"        app:secondColor="#22211a"        app:circleWidth="10dp"        app:dotCount="6"        app:currentCount="4"        app:splitSize="40"        app:bg="@drawable/clock_dial"         /></RelativeLayout>

3.5 CustomViewActivity3.java

package com.example.administrator.customview.customview03;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.util.Log;import android.view.KeyEvent;import com.example.administrator.customview.R;public class CustomViewActivity3 extends ActionBarActivity  {    public static final String TAG = "CustomVolumControlBar";    private CustomVolumControlBar customVolumControlBar01;    private CustomVolumControlBar customVolumControlBar02;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_custom_view_activity3);        init();    }    private void init() {        customVolumControlBar01 = (CustomVolumControlBar) findViewById(R.id.customVolumControlBar01);        customVolumControlBar02 = (CustomVolumControlBar) findViewById(R.id.customVolumControlBar02);    }    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        switch (keyCode) {            case KeyEvent.KEYCODE_VOLUME_DOWN:                Log.i(TAG,"KEYCODE_VOLUME_DOWN");                customVolumControlBar01.down();                customVolumControlBar02.down();                return true;            case KeyEvent.KEYCODE_VOLUME_UP:                customVolumControlBar01.up();                customVolumControlBar02.up();                return true;        }        return super.onKeyDown(keyCode, event);    }}

参考资料:

1.Android 自定义View (一)

http://blog.csdn.net/lmj623565791/article/details/24252901

2.Android 自定义View (二) 进阶

http://blog.csdn.net/lmj623565791/article/details/24300125

3.Android 自定义View (三) 圆环交替 等待效果

http://blog.csdn.net/lmj623565791/article/details/24500107

4.Android 自定义View (四) 视频音量调控

http://blog.csdn.net/lmj623565791/article/details/24529807

0 0