自定义音量调节控件的实现

本篇文章,将介绍如何实现自定义的音量调节控件。

话不多少,先看效果图

本篇文章将介绍两种实现的方式,上面的是通过继承RatingBar,然后设置样式获得的效果,下面的是通过继承自View,完全自定义的方式实现。

我们首先介绍第一种方式,也就是继承自RatingBar实现。

public class WmtRatingBar extends RatingBar {

    private OnRatingBarChanging mOnRatingBarChanging;

    public WmtRatingBar(Context context) {
        super(context);
    }

    public WmtRatingBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public WmtRatingBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP:
                if (mOnRatingBarChanging != null)
                    mOnRatingBarChanging.onRatingChanging(this.getRating());
                break;
        }
        return super.onTouchEvent(event);

    }

    public void setOnRatingBarChange(OnRatingBarChanging changing) {
        mOnRatingBarChanging = changing;
    }

    public interface OnRatingBarChanging {
        void onRatingChanging(float f);
    }

}

我们可以看到,实现方式很简单,只不过是增加了一个接口,方便获取变化值。如果我们在布局文件中需要使用的话,需要这样

<com.wike.volume.WmtRatingBar
            android:id="@+id/volume_ratingBar"
            style="@style/wmtRatingBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:numStars="15"
            android:paddingBottom="20dip"
            android:paddingTop="20dip" >
        </com.wike.volume.WmtRatingBar>

这里很重要的一个就是设置style,我们看一下在style中是如何设置的

<resources>
    <style name="wmtRatingBar" parent="@android:style/Widget.RatingBar">
        <item name="android:progressDrawable">@drawable/wmt_ratingbar</item>
        <item name="android:minHeight">16dip</item>
        <item name="android:maxHeight">16dip</item>
    </style>
</resources>

这里最重要的一个属性就是progressDrawable,这里定义了一个文件用于设置选中和不选中的图片显示,替代自带的五角星图形。

在wmt_ratingbar.xml中是这样设置的

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:id="@+android:id/background" android:drawable="@drawable/ratingbar_off"></item>
	<item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/ratingbar_off"></item>
	<item android:id="@+android:id/progress" android:drawable="@drawable/ratingbar_on"></item>
</layer-list>

在这里面设置了背景和选中时的图片显示。

通过设置这么多东西之后,我们就可以实现一开始显示出的上面那种效果,精度可以达到0.5

第一种实现方式比较简单,但是各种东西设置起来也是比较的繁琐,因此,我对第一种方案进行了修改,直接继承自View,然后完全自定义音频调节控件,下面看实现代码

/**
 * 自定义音量显示控件
 *
 * @author zhaokaiqiang
 *
 * @time 2014年6月25日 上午11:42:10
 */
public class VolumeView extends View {

	private static final String TAG = "VolumeView";
	// 增加音量图片
	private Bitmap addBitmap;
	// 减少音量图片
	private Bitmap reduceBitmap;
	// 小喇叭图片
	private Bitmap volume;
	private Paint paint = new Paint();
	// 控件高度
	private int height = 100;
	// 控件宽度
	private int width = 430;
	// 最大音量
	private int MAX = 15;
	// 两个音量矩形最左侧之间的间隔
	private int rectMargen = 15;
	// 音量矩形高
	private int rectH = 20;
	// 音量矩形宽
	private int recW = 10;
	// 当前选中的音量
	private int current = 0;
	// 最左侧音量矩形距离控件最左侧距离
	private int leftMargen = 0;

	public VolumeView(Context context) {
		super(context);
		init();
	}

	public VolumeView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		addBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.add);
		volume = BitmapFactory.decodeResource(getResources(), R.drawable.volume);
		reduceBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.reduce);
		leftMargen = volume.getWidth() + reduceBitmap.getWidth();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 绘制背景颜色
		paint.setColor(getResources().getColor(R.color.back_color));
		canvas.drawRect(0, 0, width, height, paint);

		// 绘制没有被选中的白色音量矩形
		paint.setColor(getResources().getColor(R.color.whrite));
		for (int i = current; i < MAX; i++) {
			canvas.drawRect(leftMargen + (i + 2) * rectMargen, (height - rectH) / 2, leftMargen + (i + 2) * rectMargen + recW, (height - rectH) / 2 + rectH,
					paint);
		}

		// 绘制被选中的橘黄色音量矩形
		paint.setColor(getResources().getColor(R.color.orange));
		for (int i = 0; i < current; i++) {
			canvas.drawRect(leftMargen + (i + 2) * rectMargen, (height - rectH) / 2, leftMargen + (i + 2) * rectMargen + recW, (height - rectH) / 2 + rectH,
					paint);
		}
		// 绘制音量图片
		canvas.drawBitmap(volume, volume.getWidth() / 2, (height - volume.getHeight()) / 2, paint);
		// 绘制音量减少图片
		canvas.drawBitmap(reduceBitmap, reduceBitmap.getWidth() / 2 + volume.getWidth(), (height - reduceBitmap.getHeight()) / 2, paint);
		// 绘制音量增加图片
		canvas.drawBitmap(addBitmap, leftMargen + (MAX + 2) * rectMargen, (height - addBitmap.getHeight()) / 2, paint);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_MOVE:
			// 当触摸位置在音量矩形之内时,获取当前选中的音量矩形数量
			if ((event.getX() > leftMargen + rectMargen && event.getX() < leftMargen + (MAX + 1) * rectMargen + recW)
					&& (event.getY() > (height - rectH) / 2 && event.getY() < (height - rectH) / 2 + rectH)) {
				current = (int) ((event.getX() - (leftMargen)) / (rectMargen)) - 1;
				if (onChangeListener != null) {
					onChangeListener.onChange(current);
				}
				Log.d(TAG, "current:" + current);
			}
			break;
		}
		// 通知界面刷新
		invalidate();
		// 拦截触摸事件
		return true;
	}

	// 高度父布局要占用的位置大小
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(width, height);
	}

	public interface OnChangeListener {
		public void onChange(int count);
	}

	private OnChangeListener onChangeListener;

	public void setOnChangeListener(OnChangeListener onChangeListener) {
		this.onChangeListener = onChangeListener;
	}

}

通过这个自定义的类,我们就实现了这个音量调节控件,下面我们看一下使用方法。

在布局文件中

 <com.wike.volume.VolumeView
        android:id="@+id/volumeView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

在Activity中调用

view.setOnChangeListener(new OnChangeListener() {

			@Override
			public void onChange(int count) {
				tv.setText("当前音量:"+count);
			}
		});

我们可以看到,这样使用起来很方便,但是精度暂时只能达到1的程度,而且现在增减音量的图片还是摆设,暂时没什么功能。如果有高手能帮我改进一下,不胜感激!

上面是图片资源

下面是颜色值

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="back_color">#b0000000</color>
    <color name="whrite">#ffffff</color>
	<color name="orange">#FFB90F</color>
</resources>

自定义音量调节控件的实现

时间: 2024-10-13 18:25:50

自定义音量调节控件的实现的相关文章

【Cocos2dx】利用音量螺旋控件控制血量条

其实主要是利用一个小例子来说明两个控件如何使用,一个是CCControlPotentiometer音量螺旋控件,另一个是如何利用CCControlSlider控件整出游戏中常见的血量条. 如图,随着音量螺旋控件的扭动,血量条在变化. 制作过程如下: 一.基本准备 1.首先同样还是利用(cocos2d-x-2.2.6安装目录)\tools\project-creator下的create_project.py用python命令创建一个名为PotentiometerSlider的工程.这里在<[Coc

[转]Oracle分页之二:自定义web分页控件的封装

本文转自:http://www.cnblogs.com/scy251147/archive/2011/04/16/2018326.html 上节中,讲述的就是Oracle存储过程分页的使用方式,但是如果大量的页面要使用这个分页存储过程,如果利用上节的方式,势必要书写大量的代码.如何才能够少些代码书写量呢?当然了,利用自定义web控件进行一下封装,也许是一个好方法,但是如何进行封装呢? 首先,就是在项目中添加一个“Web 用户控件“的页面,我们定义为:MyPagination.ascx 然后,就是

自定义水晶按钮控件

namespace 自定义水晶按钮控件 { partial class Form1 { /// <summary> /// 必需的设计器变量. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源. /// </summary> /// <param name="disposing&quo

自定义web用户控件ascx

在页面中使每个产品类别都展示重复的样式又想代码简洁,这时就要设置一个自定义控件. 拖入一个Repeater控件设置好样式 在page_load事件下面写一个属性: protected voidPage_Load(object sender, EventArgs e) { if(!isPostBack) { var data=new T_UserTableAdapter().GetDataById(CatId); Repeater1.DataSource=data; //手动绑定控件 Repeat

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作) 一.简单说明 使用数据刷新框架: 该框架提供了两种刷新的方法,一个是使用block回调(存在循环引用问题,_ _weak),一个是使用调用. 问题:在进行下拉刷新之前,应该要清空之前的所有数据(在刷新数据这个方法中). 移除正在显示的cell: (1)把字典中的所有的值,都从屏幕上移除 (2)清除字典中的所有元素 (3)清除cell的frame,每个位置的cell的frame都要重新计算 (4)清除可复用的缓存池. 该部分的代码如下: 1

iOS开发UI篇—自定义瀑布流控件(基本实现)

iOS开发UI篇—自定义瀑布流控件(基本实现) 一.基本实现 说明:在View加载的时候,刷新数据. 1.实现代码 YYViewController.m文件 1 // 2 // YYViewController.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-28. 6 // Copyright (c) 2014年 wendingding. All rights reserved. 7 // 8 9 #import "YYViewControll

如何在XAF中显示自定义窗体和控件

https://www.devexpress.com/Support/Center/Example/Details/E911 如何在XAF中显示自定义窗体和控件,布布扣,bubuko.com

kettle系列-[KettleUtil]kettle插件,类似kettle的自定义java类控件

该kettle插件功能类似kettle现有的定义java类插件,自定java类插件主要是支持在kettle中直接编写java代码实现自定特殊功能,而本控件主要是将自定义代码转移到jar包,就是说自定义功能的实现改为在eclipse等ide中开发. 设计本插件的原因是直接在kettle中写java代码是很不容易的事,开发体验与eclipse差得远,java语法还要受到限制,调试麻烦.实现点简单的逻辑还行,稍微复杂一点就比较麻烦,需要对java和kettle相关接口很熟悉.而简单的功能可以采用jav

CSpinButtonCtrl数字调节控件

CSpinButtonCtrl常用属性 CSpinButtonCtrl类常用成员函数 CSpinButtonCtrl代码示例   一.CSpinButtonCtrl控件属性 1.添加EDIT控件 2.添加Spin控件    如果不是这样的顺序的话,使用ctrl+D改变Tab顺序,使spin紧靠edit后面 3.在EDIT控件上面设置group属性(特别注意) 4.设置Spin属性 Auto Buddy 为     //为 true 表示按Z序自动关联一个伙伴窗口 Set Buddy Intege