深度自定义的propressBar和seekBar,可竖直显示,继承自View

android本身提供的progressBar和seekBar也可以自定义很多属性和样式,可是有时候在面对产品的诸多UI和功能要求时,我们会发现系统控件有时候并不是那么好用,功能不能做到随心所欲。

楼主最近在做电视上的设置项目,需要用到各种各样的propressBar和seekBar,横着的,竖着的,样式千奇百怪,实在是很蛋疼,最后自己继承自View写了一个比较统一且样式设置灵活的progressBar。

首先自定义了几个xml属性

    <declare-styleable name="TvProgressBar">
        <!-- 背景图片 -->
        <attr name="background" format="reference" />
        <!-- 已走过的进度图片 -->
        <attr name="progress" format="reference" />
        <!-- 滑块图片 -->
        <attr name="thumb" format="reference" />
        <!-- 滑块宽度 -->
        <attr name="thumbWidth" format="reference|dimension" />
        <!-- 进度条宽度 -->
        <attr name="progressWidth" format="reference|dimension" />
        <!-- 进度条方向       0:水平      1:竖直 -->
        <attr name="orientation" format="reference|integer" />
    </declare-styleable>

自定义了6个xml属性,分别代表:

background: 进度条的背景图片
progress:  进度条中已经走过的进度用什么图片显示
thumb:针对seekBar的属性,即滑块用什么什么图片显示
thumbWidth:针对seekBar的属性,滑块的宽度
progressWidth:进度条的宽度(已走过的进度宽度)
orientation:进度条的方向(水平或者竖直)

xml中的调用示例

    <com.pptv.tv.view.base.CustomSeekBar
        android:id="@+id/progressbar"
        android:layout_width="100dp"
        android:layout_height="350dp"
        tv:background="@drawable/sound_progress_bg"
        tv:orientation="@integer/pptv_orientation_vertical"
        tv:progressWidth="2dp"
        tv:thumb="@drawable/sound_progress_point"
        tv:thumbWidth="12dp" />

出来的效果如下图所示:

图片资源就不列了,

sound_progress_point就是那个圆形蓝色的滑块,
sound_progress_bg就是那条白色的细线
pptv_orientation_vertical = 1,表示方向竖直。

下面附上类的代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;

import com.pptv.tv.R;

public class CustomSeekBar extends View {

    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;

    private Drawable mBackGroundDrawable;
    private Drawable mProgressDrawable;
    private Drawable mThumbDrawable;

    private int mOrientation = 0;

    private int mProgressWidth = 0;
    private int mThumbWidth = 0;
    private int maxProgress = 100;

    private int mProgress = 50;

    private OnSeekBarChangeListener mSeekBarChangeListener;

    public CustomSeekBar(Context context) {
        this(context, null);
    }

    public CustomSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.TvProgressBar, defStyle, 0);
        mBackGroundDrawable = a
                .getDrawable(R.styleable.TvProgressBar_background);
        mProgressDrawable = a.getDrawable(R.styleable.TvProgressBar_progress);
        mThumbDrawable = a.getDrawable(R.styleable.TvProgressBar_thumb);
        mProgressWidth = a.getDimensionPixelSize(
                R.styleable.TvProgressBar_progressWidth, 0);
        mThumbWidth = a.getDimensionPixelSize(
                R.styleable.TvProgressBar_thumbWidth, 0);
        mOrientation = a.getInteger(R.styleable.TvProgressBar_orientation, 0);
        a.recycle();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();
        if (width <= 0 || height <= 0) {
            return;
        }

        float rate = ((float) mProgress) / maxProgress;

        // 画背景
        if (mBackGroundDrawable != null) {
            int bgleft = 0,bgright=0,bgtop=0,bgbottom=0;
            if (mOrientation == HORIZONTAL){
                bgleft = mThumbWidth / 2;
                bgright = width - mThumbWidth / 2;
                bgtop = (height - mProgressWidth) / 2;
                bgbottom = bgtop + mProgressWidth;
            }else if (mOrientation == VERTICAL){
                bgleft = (width - mProgressWidth) / 2;
                bgright = bgleft + mProgressWidth;
                bgtop = mThumbWidth / 2;
                bgbottom = height - mThumbWidth / 2;
            }
            mBackGroundDrawable.setBounds(bgleft, bgtop, bgright, bgbottom);
            mBackGroundDrawable.draw(canvas);
        }

        // 画进度条
        if (mProgressDrawable != null) {
            int progressleft=0,progressright=0,progresstop=0,progressbottom=0;
            if (mOrientation == HORIZONTAL){
                progressleft = mThumbWidth / 2;
                progressright = (int) (progressleft + rate
                        * (width - mThumbWidth));
                progresstop = (height - mProgressWidth) / 2;
                progressbottom = progresstop + mProgressWidth;
            }else if (mOrientation == VERTICAL){
                progressleft = (width - mProgressWidth) / 2;
                progressright = progressleft + mProgressWidth;
                progressbottom = height - mThumbWidth / 2;
                progresstop = (int) (progressbottom - rate
                        * (height - mThumbWidth));
            }
            mProgressDrawable.setBounds(progressleft, progresstop,
                    progressright, progressbottom);
            mProgressDrawable.draw(canvas);
        }

        // 画滑块
        if (mThumbDrawable != null) {
            int thumbleft=0,thumbright=0,thumbtop=0,thumbbottom=0;
            if (mOrientation == HORIZONTAL){
                thumbleft = (int) ((width - mThumbWidth) * rate);
                thumbright = thumbleft + mThumbWidth;
                thumbtop = (height - mThumbWidth) / 2;
                thumbbottom = thumbtop + mThumbWidth;
            }else if (mOrientation == VERTICAL){
                thumbleft = (width - mThumbWidth) / 2;
                thumbright = thumbleft + mThumbWidth;
                thumbbottom = (int) (height - rate * (height - mThumbWidth));
                thumbtop = thumbbottom - mThumbWidth;
            }
            mThumbDrawable.setBounds(thumbleft, thumbtop, thumbright,
                    thumbbottom);
            mThumbDrawable.draw(canvas);
        }

    }

    public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
        mSeekBarChangeListener = listener;
    }

    public interface OnSeekBarChangeListener {
        public abstract void onProgressChanged();

    }

    public void setOrientation(int orientation){
        mOrientation = orientation;
        invalidate();
    }

    public void setProgress(int progress) {

        if (progress < 0 || progress > maxProgress) {
            return;
        }

        mProgress = progress;
        invalidate();
        if (mSeekBarChangeListener != null) {
            mSeekBarChangeListener.onProgressChanged();
        }

    }

    public int getProgress() {
        return mProgress;
    }

    public int getMaxProgress() {
        return maxProgress;
    }

    public boolean increase() {
        if (mProgress < maxProgress) {
            mProgress++;
            setProgress(mProgress);
            return true;
        }
        return false;
    }

    public boolean reduce() {
        if (mProgress > 0) {
            mProgress--;
            setProgress(mProgress);
            return true;
        }
        return false;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (mOrientation == HORIZONTAL) {
            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                if (mProgress > 0) {
                    mProgress--;
                    setProgress(mProgress);
                    return true;
                }

            }

            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (mProgress < maxProgress) {
                    mProgress++;
                    setProgress(mProgress);
                    return true;
                }

            }
        }

        if (mOrientation == VERTICAL) {

            if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                if (mProgress > 0) {
                    mProgress--;
                    setProgress(mProgress);
                    return true;
                }

            }

            if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                if (mProgress < maxProgress) {
                    mProgress++;
                    setProgress(mProgress);
                    return true;
                }

            }

        }

        return super.onKeyDown(keyCode, event);
    }
}
重点是在onDraw里面的涂鸦,根据当前进度分别画背景,画进度条,画滑块。代码应该还是很好理解的就不做详细说明了。

				
时间: 2024-08-03 13:46:52

深度自定义的propressBar和seekBar,可竖直显示,继承自View的相关文章

竖直显示字符串UILabel

//怎么将字符串中的每一个字符存入数组中 NSString *[email protected]"中华人民共和国";    NSMutableArray *stringArray = [[NSMutableArray alloc] init];    for (int i = 0; i < textString.length; i ++) {        NSRange range;        range.location = i;        range.length

自定义特效VIew第一弹之竖直TextView

自定义特效VIew第一弹之竖直TextView 别的不说,先给出效果 再给出代码 <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.empty.VerticalTextView android:layout_width="wrap_content" android:layout_

fusioncharts &nbsp; 横坐标x 标签 竖着显示

labelDisplay='WRAP' slantLabels='0'  横坐标空间够的时候 标签横向展示,当不够的时候自动换行或者竖着显示 labelDisplay='ROTATE' slantLabels='0'  横坐标标签竖着显示,但是中文标签,也旋转了90° labelDisplay='NONE' slantLabels='0'   横坐标标签一直竖直显示 java后台横坐标数值做如下处理(给每个字之间加上\n处理): String strOther=""; String s

Android自定义竖直方向SeekBar

写在前面 因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下: 具体实现 本来想定义水平的,然后旋转一下,后来发现还不如直接定义竖直方向来的直接,就直接在竖直方向画了下. 首先讲一下思路,就是通过继承View,然后通过onDraw()方法进行绘制.具体绘制的时候,需要处理一些小细节.比如,我们需要画一个圆形的滑动块,那么我们的背景色带就不能把整个宽度占满,要不然,小圆块只能和色带一样宽了,效果不是很好看,所以在绘制的时候应该把背景

Android 自定义带刻度的seekbar

自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby.client.views.CustomSeekbar android:id="@+id/myCustomSeekBar" android:layout_width="wrap_content" android:layout_height="wrap_cont

自定义Imageview控件实现多种手势操作 (拖动、水平缩放、竖直缩放、等比例缩放、双击、长按)

项目中需要使用自定义控件的多种手势操作,之前在网上查阅资料的时候发现能找到的一般是只实现了其中的几种,这次就把我做的控件分享一下,人人为我,我为人人嘛,哈哈! 这个自定义控件实现的主要功能是控件的拖动和缩放(注意:不是对控件中的图片进行操作,话说很多帖子都把这两个混了),其中缩放可以按照三个方向进行,就是水平.竖直和等比例.双击操作只做了一个提示,长按加上了一个简单的弹出菜单. 抱歉的是没有足够的时间写详细注释了,如果跟你需要的功能相同就请直接调用,要是需要改代码就费点神自己读懂代码吧,看不懂的

android中自定义view---实现竖直方向的文字功能,文字方向朝上,同时提供接口,判断当前touch的是哪个字符,并改变颜色

android自定义view,实现竖直方向的文字功能,文字方向朝上,同时提供接口,判断当前touch的是哪个字符,并改变颜色. 由于时间比较仓促,因此没有对代码进行过多的优化,功能远远不如android的自带的TextView强大,只是继承于view,而不是textview. 主要用途:电话本的侧边快速导航等 效果图:(自定义字符串 “#ABCDEFGHIJKLMN),可以实现自定义任意字符串 view的实现: 1 import cn.carbs.verticalstraighttextview

Android 自定义View实现竖直跑马灯效果

首先给出效果图 中间的色块是因为视频转成GIF造成的失真,自动忽略哈. 大家知道,横向的跑马灯android自带的TextView就可以实现,详情请百度[Android跑马灯效果].但是竖直的跑马灯效果原生Android是不支持的.网上也有很多网友实现了自定义的效果,但是我一贯是不喜欢看别人的代码,所以这篇博客的思路完全是我自己的想法哈. 首先,我们需要给自定义的控件梳理一下格局,如下图所示: 1.首先我们将控件分为三个区块,上面绿色部分为消失不可见的块,中间黑色部分为可见区域,下面红色部分为欲

自定义漂亮的Android SeekBar样式

系统自带的SeekBar真是太难看了,项目需要,只能自定义了,先来张效果图 第一个Seekbar 背景是颜色,thumb是图片,上代码: [html] view plaincopy <SeekBar android:id="@+id/timeline" android:layout_width="fill_parent" android:layout_height="wrap_content" android:focusable="