android 垂直 SeekBar 源代码(VerticalSeekBar)

搬家后的博客链接: IT客栈 www.itkezhan.org


这几天需要用到垂直的 seekbar 但是android 包下翻了一下。发现没有,只能自己修改源码。


主要是继承 AbsSeekBar 然后修改下面这些方法


onProgressRefresh() //当进度条数据更新的时候,例如我们拖动滑动条的时候,这个方法被调用

setThumbPos() //这个方法是设置Thumb的位置

onDraw() //这个是负责画界面

onSizeChanged() //更新画布尺寸

onTouchEvent() //当触摸屏幕的时候被调用

trackTouchEvent() //当拖动滑动条的时候,这个被调用


还有就是添加一个接口这个接口是SeekBar 的一个内部接口 public interface OnSeekBarChangeListener

里面有三个方法:

public void onProgressChanged(VerticalSeekBar vBar, int progress,boolean fromUser);
public void onStartTrackingTouch(VerticalSeekBar vBar);
public void onStopTrackingTouch(VerticalSeekBar vBar);

这个接口主要是为外部提供监听。多说无益,大家看源代码明白一点。


import java.lang.reflect.Field;
import java.lang.reflect.Method;
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.MotionEvent;
import android.view.View;
import android.widget.AbsSeekBar;
import android.widget.SeekBar;


public class VerticalSeekBar extends AbsSeekBar { 

	private int height = -1;
	private int width = -1;
	public interface OnSeekBarChangeListener
	{
		public void onProgressChanged(VerticalSeekBar vBar, int progress,boolean fromUser);
		public void onStartTrackingTouch(VerticalSeekBar vBar);
		public void onStopTrackingTouch(VerticalSeekBar vBar);
	}
	
	private OnSeekBarChangeListener mOnSeekBarChangeListener;
	public VerticalSeekBar(Context context)
	{
		this(context, null);
	}
	
	public VerticalSeekBar(Context context, AttributeSet attrs)
	{
		this(context, attrs, android.R.attr.seekBarStyle);
	}
	
	public VerticalSeekBar(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)
	{
		Drawable thumb = null;
		try
		{
			Field mThumb_f = this.getClass().getSuperclass().getDeclaredField("mThumb");
			mThumb_f.setAccessible(true);
			thumb = (Drawable)mThumb_f.get(this);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

		setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
		
		invalidate();
		
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
        }
	}
	
	private void setThumbPos(int w, Drawable thumb, float scale, int gap)
	{
		int available = 0;
		try
		{

			int up = getPaddingTop();
			int bottom = getPaddingBottom();
			
			available = getHeight() - up - bottom;
	        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;
	        }
	        // Canvas will be translated, so 0,0 is where we start drawing
	        thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);	
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

	}
	
	 protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	 {     
		 width = 30;
         height = View.MeasureSpec.getSize(heightMeasureSpec);
 
         this.setMeasuredDimension(width, height); 
	 } 
	
	protected void onDraw(Canvas c)
	{
		c.rotate(-90);
		c.translate(-height,0); 
		super.onDraw(c);
	}
	
	protected void onSizeChanged(int w, int h, int oldw, int oldh)
	{     
        super.onSizeChanged(h, w, oldw, oldh); 
	} 
	
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
    	
    	boolean mIsUserSeekable=true;
		try
		{
	    	Field mIsUserSeekable_f = this.getClass().getSuperclass().getDeclaredField("mIsUserSeekable");
	    	mIsUserSeekable_f.setAccessible(true);

			mIsUserSeekable = mIsUserSeekable_f.getBoolean(this);
		}
		catch (Exception e1)
		{
			e1.printStackTrace();
		}
    	
        if (!mIsUserSeekable || !isEnabled()) {
            return false;
        }
        
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setPressed(true);
                onStartTrackingTouch();
                trackTouchEvent(event);
                break;
                
            case MotionEvent.ACTION_MOVE:
                trackTouchEvent(event);
                Method attemptClaimDrag;
				try
				{
					attemptClaimDrag = this.getClass().getSuperclass().getDeclaredMethod("attemptClaimDrag");
					attemptClaimDrag.setAccessible(true);
	                attemptClaimDrag.invoke(this);
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
                break;
                
            case MotionEvent.ACTION_UP:
                trackTouchEvent(event);
                onStopTrackingTouch();
                setPressed(false);
                // ProgressBar doesn't know to repaint the thumb drawable
                // in its inactive state when the touch stops (because the
                // value has not apparently changed)
                invalidate();
                break;
                
            case MotionEvent.ACTION_CANCEL:
                onStopTrackingTouch();
                setPressed(false);
                invalidate(); // see above explanation
                break;
        }
        return true;
    }
    
    protected void trackTouchEvent(MotionEvent event)
    {
    	
        final int height = getHeight();
        final int available = height - getPaddingLeft() - getPaddingRight();
        int y = (int)(height - event.getY());
        float scale;
        float progress = 0;
        if (y < getPaddingLeft()) {
            scale = 0.0f;
        } else if (y > height - getPaddingRight()) {
            scale = 1.0f;
        } else {
            scale = (float)(y - getPaddingLeft()) / (float)available;
            float mTouchProgressOffset = 0.0f;
            try
            {
            	Field mTouchProgressOffset_f = this.getClass().getSuperclass().getDeclaredField("mTouchProgressOffset");
            	mTouchProgressOffset_f.setAccessible(true);
            	mTouchProgressOffset = mTouchProgressOffset_f.getFloat(this);
            }
            catch(Exception e)
            {
    			e.printStackTrace();
            }
            progress = mTouchProgressOffset;
        }
        
        final int max = getMax();
        progress += scale * max;
        
        try
        {
        	Method setProgress = this.getClass().getSuperclass().getSuperclass().getDeclaredMethod("setProgress", int.class,boolean.class);
        	setProgress.setAccessible(true);
        	setProgress.invoke(this, (int)progress, true);
        }
        catch(Exception e)
        {
			e.printStackTrace();
        }
    }
}


一个运行的截图


转载请注明出处,祝新年快乐。

本文链接:

http://blog.csdn.net/failure01/article/details/8577675

参考文档链接:

http://www.eoeandroid.com/thread-430-1-1.html

http://blog.csdn.net/saintswordsman/article/details/5248233

你可能感兴趣的:(android 垂直 SeekBar 源代码(VerticalSeekBar))