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

    通过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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hfreeman2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值