当前位置: 代码迷 >> Android >> Android惯用控件之SeekBar的使用
  详细解决方案

Android惯用控件之SeekBar的使用

热度:55   发布时间:2016-05-01 09:54:00.0
Android常用控件之SeekBar的使用


SeekBar的应用非常广,比如用来显示音量条、播放进度条,有水平显示也有垂直显示,但Android只给我们提供了水平的,可以用系统默认的样式也可以用我们自定义的样式,总之进度条的用法多种多样,如果Android没有提供也能我们自己去定制,先上图


使用图片自定义水平进度条时有个缺陷,就是图片不能根据进度条的大小进行拉伸,也就是自适应进度条的长度。当然也可以通过改变进度条的宽度跟图片宽度一致,这样就不会出现上面的情况。我想让图片适应进度条的大小,但还没找到解决办法,我想通过广大网友一起想想办法如何解决这样问题,有知道的朋友可以告诉我,感激不尽!

上图显示的第一个进度条是Android定义的,我们不需要做任何更新,只需要在布局文件中添加就可以,如

<SeekBar        android:id="@+id/seekbar"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true" />

然后在Activity中根据相应的ID获取对象,并添加监听器


下面看下第二个进度条的在布局文件中的定义

<SeekBar        android:id="@+id/proSeek"        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@id/seekbar"        android:layout_gravity="center_vertical"        android:paddingLeft="5dp"        android:paddingRight="5dp"        android:progressDrawable="@drawable/seekbar_style"        android:secondaryProgress="0"        android:thumb="@drawable/thumb_selector" />

进度条样式seekbar_style.xml定义 以下是使用图片定义的

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"     android:opacity="transparent">    <item        android:id="@android:id/background"        android:drawable="@drawable/player_progress_bg"/>    <item        android:id="@android:id/secondaryProgress"        android:drawable="@drawable/player_progress_buffering">    </item>    <item        android:id="@android:id/progress"        android:drawable="@drawable/player_progress_playing">    </item></layer-list>


滑块thumb_selector.xml 定义

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@drawable/voice_thumb_press"         android:state_pressed="true"/>    <item android:drawable="@drawable/voice_thumb_normal"         android:state_enabled="true"         android:state_focused="true"         android:state_window_focused="true"/>    <item android:drawable="@drawable/voice_thumb_normal"/></selector>
至此一个用图片定义的进度条就完成了。

第三个进度条是修改了滑块,这就需要重写SeekBar

关键代码如下:

在布局文件中声明自定义的控件  com.example.seekbar.mSeekBar

<com.example.seekbar.mSeekBar        android:id="@+id/proSeek2"        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@id/proSeek"        android:layout_gravity="center_vertical"        android:paddingLeft="5dp"        android:paddingRight="5dp"        android:progressDrawable="@drawable/seekbar_style_1"        android:secondaryProgress="0"        android:thumb="@drawable/thumb_selector" />

修改滑块的关键代码

public mSeekBar(Context context, AttributeSet attrs) {		super(context, attrs);		paint = new Paint();		paint.setTextAlign(Paint.Align.CENTER);		paint.setColor(Color.BLUE);		res = context.getResources();		bmp = BitmapFactory.decodeResource(res, R.drawable.voice_thumb_press);		thumb = new BitmapDrawable(res, bmp);		bmpPro = BitmapFactory.decodeResource(res, R.drawable.player_progress_bg);		Progress = new BitmapDrawable(res, bmpPro);		// 判断屏幕大小 符合条件进行缩放thumb		if (Pixels.getpixels_x(100) < ScreenWidth				&& Pixels.getpixels_y(100) < screenHeight) {			thumb = zoomDrawable(thumb, bmp.getWidth(), bmp.getHeight());		} else {			paint.setTextSize(20);		}		Progress = zoomDrawable(Progress, bmpPro.getWidth(), bmpPro.getHeight());		// 设置拖动的图片		setThumb(thumb);		// 图片的位置		setThumbOffset(thumb.getIntrinsicWidth());		setBackgroundDrawable(Progress);	}

第四个进度条是用颜色来填充

主要是下面这个样式文件   

seekbar_style_own.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">        <shape>            <corners android:radius="5dip" />            <gradient                android:angle="270"                android:centerColor="#ff5a5d5a"                android:centerY="0.75"                android:endColor="#ff747674"                android:startColor="#ff9d9e9d" />        </shape>    </item>    <item android:id="@android:id/secondaryProgress">        <clip>            <shape>                <corners android:radius="5dip" />                <gradient                    android:angle="270"                    android:centerColor="#80ffb600"                    android:centerY="0.75"                    android:endColor="#a0ffcb00"                    android:startColor="#80ffd300" />            </shape>        </clip>    </item>    <item android:id="@android:id/progress">        <clip>            <shape>                <corners android:radius="5dip" />                <gradient                    android:angle="270"                    android:centerColor="#ff3399CC"                    android:centerY="0.75"                    android:endColor="#ff6699CC"                    android:startColor="#ff0099CC" />            </shape>        </clip>    </item></layer-list>

布局文件中声明如下:

<SeekBar        android:id="@+id/proSeek1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_below="@id/proSeek2"        android:paddingBottom="10dp"        android:paddingLeft="5dp"        android:paddingRight="5dp"        android:paddingTop="10dp"        android:progressDrawable="@drawable/seekbar_style_own"        android:secondaryProgress="0"        android:thumb="@drawable/thumb_selector" />

再下面就是垂直滑动条的实现

布局文件中声明

<com.example.seekbar.verSeekBar        android:id="@+id/verBar"        android:layout_width="30dip"        android:layout_height="match_parent"        android:layout_below="@id/proSeek1"        android:progressDrawable="@drawable/seekbar_style_own" />

verSeekBar.java文件
package com.example.seekbar;/* *Author: tanrui *Date: 20/1/2010 */import android.content.Context;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.View;import android.widget.AbsSeekBar;public class verSeekBar extends AbsSeekBar {	private Drawable mThumb;	private int height;	private int width;		public static final int TOP = 0;	public static final int BUTTOM = 1;		private int mntype = TOP;		public interface OnSeekBarChangeListener {		void onProgressChanged(verSeekBar VerticalSeekBar, int progress,				boolean fromUser);		void onStartTrackingTouch(verSeekBar VerticalSeekBar);		void onStopTrackingTouch(verSeekBar VerticalSeekBar);	}	private OnSeekBarChangeListener mOnSeekBarChangeListener;	public verSeekBar(Context context) {		this(context, null);	}	public verSeekBar(Context context, AttributeSet attrs) {		this(context, attrs, android.R.attr.seekBarStyle);	}	public verSeekBar(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);	}	public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {		mOnSeekBarChangeListener = l;	}	void onStartTrackingTouch() {		if (mOnSeekBarChangeListener != null) {			mOnSeekBarChangeListener.onStartTrackingTouch(this);		}	}	void onStopTrackingTouch() {		if (mOnSeekBarChangeListener != null) {			mOnSeekBarChangeListener.onStopTrackingTouch(this);		}	}	void onProgressRefresh(float scale, boolean fromUser) {		Log.i("6", "onProgressRefresh==>scale"+scale);		Drawable thumb = mThumb;		if (thumb != null) {			setThumbPos(getHeight(), thumb, scale, Integer.MIN_VALUE);			invalidate();		}		if (mOnSeekBarChangeListener != null) {			mOnSeekBarChangeListener.onProgressChanged(this, getProgress(),					fromUser);		}	}		public void setType(int type)	{		mntype = type;	}	private void setThumbPos(int w, Drawable thumb, float scale, int gap) {		Log.i("6", "setThumbPos==>w"+w);		int available = w + getPaddingLeft() - getPaddingRight();		int thumbWidth = thumb.getIntrinsicWidth();		int thumbHeight = thumb.getIntrinsicHeight();		available -= thumbWidth;		// The extra space for the thumb to move on the track		available += getThumbOffset()* 2;		int thumbPos = (int) (scale * available);		int topBound, bottomBound;		if (gap == Integer.MIN_VALUE) {			Rect oldBounds = thumb.getBounds();			topBound = oldBounds.top;			bottomBound = oldBounds.bottom;		} else {			topBound = gap;			bottomBound = gap + thumbHeight;		}		thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);	}	protected void onDraw(Canvas c) {		Log.i("6", "onDraw==>height"+height);		if(mntype == TOP)		{		c.rotate(90);		c.translate(0, -width);		}		else {			c.rotate(-90);			c.translate(-height, 0);		}		super.onDraw(c);	}	protected synchronized void onMeasure(int widthMeasureSpec,			int heightMeasureSpec) {		// width = 200;		// height = 120;		height = View.MeasureSpec.getSize(heightMeasureSpec);		width = View.MeasureSpec.getSize(widthMeasureSpec);		Log.i("6", "onMeasure==>height,,width"+height+"     "+width);		this.setMeasuredDimension(width, height);	}	@Override	public void setThumb(Drawable thumb) {		mThumb = thumb;		super.setThumb(thumb);	}	protected void onSizeChanged(int w, int h, int oldw, int oldh) {		Log.i("6", "onSizeChanged==>w,,h,,oldw,,oldh"+w+"     "+h+"     "+oldw+"     "+oldh);		super.onSizeChanged(h, w, oldw, oldh);	}	public boolean onTouchEvent(MotionEvent event) {		if (!isEnabled()) {			return false;		}		switch (event.getAction()) {		case MotionEvent.ACTION_DOWN:			setPressed(true);			onStartTrackingTouch();			trackTouchEvent(event);			break;		case MotionEvent.ACTION_MOVE:			trackTouchEvent(event);			attemptClaimDrag();			break;		case MotionEvent.ACTION_UP:			trackTouchEvent(event);			onStopTrackingTouch();			setPressed(false);			break;		case MotionEvent.ACTION_CANCEL:			onStopTrackingTouch();			setPressed(false);			break;		}		return true;	}	private void trackTouchEvent(MotionEvent event) {		final int Height = getHeight();		Log.i("6", "trackTouchEvent==>Height"+Height);		final int available = Height - getPaddingBottom() - getPaddingTop();		int Y = (int) event.getY();		Log.i("6", "trackTouchEvent==>Y"+Y);		float scale;		float progress = 0;		if (Y > Height - getPaddingBottom()) {			scale = 1.0f;		} else if (Y < getPaddingTop()) {			scale = 0.0f;		} else {			scale = (float) (Y)					/ (float) available;		}		final int max = getMax();		progress = scale * max;		int temp;		if(mntype == TOP)		{			temp = (int) progress;		}		else		{			temp = (int) (max - progress);		}		setProgress(temp);	}	private void attemptClaimDrag() {		if (getParent() != null) {			getParent().requestDisallowInterceptTouchEvent(true);		}	}	public boolean dispatchKeyEvent(KeyEvent event) {		if (event.getAction() == KeyEvent.ACTION_DOWN) {			KeyEvent newEvent = null;			switch (event.getKeyCode()) {			case KeyEvent.KEYCODE_DPAD_UP:				newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,						KeyEvent.KEYCODE_DPAD_RIGHT);				break;			case KeyEvent.KEYCODE_DPAD_DOWN:				newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,						KeyEvent.KEYCODE_DPAD_LEFT);				break;			case KeyEvent.KEYCODE_DPAD_LEFT:				newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,						KeyEvent.KEYCODE_DPAD_DOWN);				break;			case KeyEvent.KEYCODE_DPAD_RIGHT:				newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,						KeyEvent.KEYCODE_DPAD_UP);				break;			default:				newEvent = new KeyEvent(KeyEvent.ACTION_DOWN, event						.getKeyCode());				break;			}			return newEvent.dispatch(this);		}		return false;	}}

另外一个只是更新样式就可以,这里就不写出来了,附上源码供大家参考

点击打开链接

上面提到的图片不能根据控件大小进行拉伸找到解决办法了,原来Android给我们提供了一个工具制作9.png格式的文件,这种格式的图片可以根据控件大小自适应调节大小而不失真。这个工具是draw9patch.bat  在Android  SDK的tools目录下可以找到。来看下修改过后的效果


是不是比上面那张好看多了,只需要把.png格式的图片用工具改成9.png格式就OK了。

在这里需要感谢石同事给我的帮助!



  相关解决方案