Android 自定义星级评分控件

自定义Android 星级评分控件,先上一下效果图

关于控件的制作步骤:

1.首先要确定控件所需要用到的属性,那位作为一个星级评分的控件,能想到的就是大小,形状,数量,评分设置标准,是否允许点击操作,监听等内容,所以我定义了以下属性


public class Star extends View {
    //星星评分
    private float starMark = 0.0F;
    //星星个数
    private int starNum = 5;
    //星星高度
    private int starHeight;
    //星星宽度
    private int starWidth;
    //星星间距
    private int starDistance;
    //星星背景
    private Drawable starBackgroundBitmap;
    //动态星星
    private Bitmap starDrawDrawable;
    //星星变化监听
    private OnStarChangeListener changeListener;
    //是否可以点击
    private boolean isClick = true;
    //画笔
    private Paint mPaint;
}
然后为这个类添加两个构造方法

   public Star(Context mContext, AttributeSet attrs) {
        super(mContext, attrs);
    }

    public Star(Context mContext, AttributeSet attrs, int defStyleAttr) {
        super(mContext, attrs, defStyleAttr);
    }
可能有些人不理解attrs这个参数的作用,在我们使用过的很多自定义控件的构造方法里都会涉及到,他的作用就是来传递自定义的控件在xml里布局设置的对应的属性。

2.经过1步骤之后,可以说自定义类的框架已经出来了,接着了解下自定义布局的核心的内容。我找了一张绘制view的流程图

这个图的意思就是绘制view的主要三个步骤,measure测量,layout布局,draw绘制,测量控件所占用的宽高,决定把他放在那块布局上,然后画出来我们要的样式,不一定每个步骤都需要自己来完成,自己做自定义的话只需要完成draw这一步就可以了,像图中所说的方法measure();layout();draw();是不能被直接重写的,但是给我们提供了可以重写的方法,onMeasure();onLayout();onDraw();我重写了onMeasure();onDraw();两个方法,道理是如果像自己的控件支持设置宽高度warp_content,那么必须重写下这个方法,ondraw();是真正这次作自定义需要的内容,关于自定义view的原理,我这边找到了一篇很好文章,分享给大家https://gold.xitu.io/entry/580467dc8ac24700580a4b1a

下面是我重写的ondraw()的内容

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (null == starDrawDrawable || null == starBackgroundBitmap) {
            return;
        }
        for (int i = 0; i < starNum; i++) {
            starBackgroundBitmap.setBounds(starDistance * i + starWidth * i, 0, starWidth * (i + 1) + starDistance * i, starHeight);
            starBackgroundBitmap.draw(canvas);
        }
        if (starMark > 1) {//是否只有一颗星
	    //如果超过一颗星,先画一颗星,在判断是否剩下的是整颗的某几颗星,如果是整颗,直接剩下几颗画几颗,如果不是,画完整颗的在画剩余的
            canvas.drawRect(0, 0, starWidth, starHeight, mPaint);
            if (starMark - (int) (starMark) == 0) {
                for (int i = 1; i < starMark; i++) {
                    canvas.translate(starDistance + starWidth, 0);
                    canvas.drawRect(0, 0, starWidth, starHeight, mPaint);
                }
            } else {
                for (int i = 1; i < starMark - 1; i++) {
                    canvas.translate(starDistance + starWidth, 0);
                    canvas.drawRect(0, 0, starWidth, starHeight, mPaint);
                }
                canvas.translate(starDistance + starWidth, 0);
                canvas.drawRect(0, 0, starWidth * (Math.round((starMark - (int) (starMark)) * 10) * 1.0f / 10), starHeight, mPaint);
            }
        } else {
	    //如果不到一颗星,直接mark多少就画多少
            canvas.drawRect(0, 0, starWidth * starMark, starHeight, mPaint);
        }

    }
关于canvas方法,就不解释了,网上内容很多,到此,核心的东西就没有了。

接着展示下初始化控件的方法,

private void init(Context mContext, AttributeSet attrs) {

        //初始化控件属性
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.star);
        starNum = typedArray.getInteger(R.styleable.star_starsNum, 5);
        starHeight = (int) typedArray.getDimension(R.styleable.star_starHeight, 0);
        starWidth = (int) typedArray.getDimension(R.styleable.star_starWidth, 0);
        starDistance = (int) typedArray.getDimension(R.styleable.star_starDistance, 0);
        isClick = typedArray.getBoolean(R.styleable.star_starClickable, true);
        starBackgroundBitmap = typedArray.getDrawable(R.styleable.star_starBackground);
        starDrawDrawable = drawableToBitmap(typedArray.getDrawable(R.styleable.star_starDrawBackground));
        typedArray.recycle();
        setClickable(isClick);
        //初始化画笔
        mPaint = new Paint();
        //设置抗锯齿
        mPaint.setAntiAlias(true);
        mPaint.setShader(new BitmapShader(starDrawDrawable, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
    }
利用typedArray 获取xml设置的控件属性,xml设置如下

<ratingstar.yueleng.com.freedomstar_master.Star
                android:id="@+id/star"
                Star:starsNum ="5"
                Star:starWidth ="18dp"
                Star:starHeight ="18dp"
                Star:starDistance ="3dp"
                Star:starBackground ="@drawable/s2"
                Star:starDrawBackground ="@drawable/s1"
                Star:starClickable ="false"
                android:layout_marginLeft="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>


attrs.xml内容是这样的

<declare-styleable name="star">
        //星星数量
        <attr format="integer" name="starsNum"></attr>
        //星星宽度
        <attr format="dimension" name="starWidth"></attr>
        //星星高度
        <attr format="dimension" name="starHeight"></attr>
        //星星间距
        <attr format="dimension" name="starDistance"></attr>
        //星星背景
        <attr format="reference" name="starBackground"></attr>
        //星星变化背景
        <attr format="reference" name="starDrawBackground"></attr>
        //控件是否可以点击
        <attr format="boolean" name="starClickable"></attr>

    </declare-styleable>


一个转化bitmap的方法

/**
     * drawable转bitmap
     */
    public Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable == null) return null;
        Bitmap bitmap = Bitmap.createBitmap(starWidth, starHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, starWidth, starHeight);
        drawable.draw(canvas);
        return bitmap;
    }



添加按钮滑动点击控制

public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        if (x < 0)
            x = 0;
        if (x > getMeasuredWidth())
            x = getMeasuredWidth();
        if (isClick) {
            switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    setMark(x * 1.0f / (getMeasuredWidth() * 1.0f / starNum));
                    break;
                case MotionEvent.ACTION_MOVE:
                    setMark(x * 1.0f / (getMeasuredWidth() * 1.0f / starNum));
                    break;
                case MotionEvent.ACTION_UP:
                    setMark(x * 1.0f / (getMeasuredWidth() * 1.0f / starNum));
                    break;
            }
        }
        return true;
    }


至此项目就完成了,有些细节的地方没有说,如果感兴趣的朋友,可以下载下来看看,不足的地方欢迎建议。

csdn:http://download.csdn.net/detail/z690798364/9735752
github:https://github.com/songfuli/freedomstar-ratingbar


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android自定义View是指基于Android原生控件的一种扩展,可以根据自己的需求和设计规范来创建更加个性化和独特的控件。而歌词控件是一种针对音乐播放器或者视频播放器等应用场景中的需求,用于显示音乐或者视频的歌词的控件Android自定义View歌词控件的实现思路如下: 1. 首先需要自定义一个View,并继承自View或者其子类,如TextView。 2. 在自定义的View中重写onDraw方法,在其中实现绘制歌词的逻辑。 3. 在onDraw方法中,使用Canvas对象进行绘制,可以使用drawText方法绘制歌词文本,也可以使用drawBitmap方法绘制图片背景等。 4. 可以通过自定义属性,如字体大小、字体颜色、歌词滚动速度等,来对歌词控件进行配置。 5. 如果需要实现歌词的滚动效果,可以使用ValueAnimator或者Scroller来实现歌词的平滑滚动。 6. 如果需要实现点击歌词跳转播放进度的功能,可以通过添加点击事件监听器,在触摸事件中判断点击位置对应的歌词行,并根据歌词的时间戳跳转到指定的播放进度。 总结来说,Android自定义View歌词控件的实现需要重写onDraw方法进行绘制,可以通过Canvas对象进行绘制文本或者图像,通过自定义属性进行配置,使用动画或者滚动实现歌词的平滑滚动,通过监听触摸事件实现点击歌词跳转播放进度的功能。通过以上步骤,我们可以创建一个个性化的歌词控件,满足不同应用场景的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

子夜微凉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值