简单的列表式自定义View

记得以前刚开始学安卓的时候,做过一个模仿蜻蜓FM的Demo。他那里面的每个List元素都是一个自定义View。当时没时间做,就跳过去。在上个公司很少写自定义View,感觉都有点生疏了。正巧赶上过年有空,并且感觉这个自定义View挺简单。拿出了半天的时间简单的实现下练练手。

先看看他们的app的布局


自定义虽然麻烦,但是可以减少布局的层次。我们就来实现他这个单独的自定义View,并且单独一个View在代码里面使用起来也更方便简单。

首先是构造函数,对于这个自定义V iew我们给它留四个styleable。

    <declare-styleable name="QingtingView1" >
        <attr name="isNeedTimeStamp" format="boolean" />
        <attr name="isNeedStar" format="boolean" />
        <attr name="TitleTextSize" format="dimension"/>
        <attr name="DesTextSize" format="dimension"/>
    </declare-styleable>
分别来指定它是否需要时间戳,是否需要星级描述,以及标题和描述的字体大小

    public QingTingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.QingtingView1, defStyleAttr, 0);
        for(int count = a.getIndexCount(); count > 0; count --){
            int attr = a.getIndex(count);
            switch (attr){
                case R.styleable.QingtingView1_isNeedStar :
                    isNeedStar = a.getBoolean(attr, false);
                case R.styleable.QingtingView1_isNeedTimeStamp :
                    isNeedTimeStamp = a.getBoolean(attr, false);
                case R.styleable.QingtingView1_TitleTextSize:
                    mTitleTextSize = a.getDimensionPixelSize(attr, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
                case R.styleable.QingtingView1_DesTextSize:
                    mDesTextSize = a.getDimensionPixelSize(attr, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,14,getResources().getDisplayMetrics()));
                case R.styleable.QingtingView1_ImageRes:
                    mDrawable = a.getDrawable(attr);
            }
        }
        a.recycle();
        init();
    }

这里我们只贴有 style的这个构造函数。

<span style="font-size:18px;">    private void init() {

        mPaint = new Paint();
        mTitleTextSize =  (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics());
        mDesTextSize =  (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,14,getResources().getDisplayMetrics());
        mDrawablePadding = UIUtils.dip2px(getContext(),10);
        mHeight = UIUtils.dip2px(getContext(), 80);
    }</span>


就可以在 java代码里面获得Dp值。

    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


在OnMeasure 方法里面。我们使用默认的width。和写死的height。其中width需要进一步处理。这里只是一个demo。要拿代码用到项目里面的请注意这个东西

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(width, mHeight);
    }


最后是大头 Ondraw方法。代码较为简单。里面hardCode较多。在这里就不一行行的加奇葩的注释了。有问题可以在评论里面问。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float textStartX = 0;
        if (null == mDrawable || null == mTitle || null == mDes)
            return;
        if (mDrawable.getIntrinsicHeight() != 0 && mDrawable.getIntrinsicWidth() != 0) {
            int drawLength = mHeight - getPaddingBottom(); //由于是正方形的按照其高度进行剪切作为边长
            mDrawable.setBounds(getPaddingLeft(), getPaddingTop(),drawLength,drawLength);
            mDrawable.draw(canvas);
            textStartX = drawLength + mDrawablePadding;
        }
        //标题
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize(mTitleTextSize);
        Rect titleBound = new Rect();
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), titleBound);
        canvas.drawText(mTitle, textStartX, (titleBound.height() + getPaddingTop()), mPaint);

        //说明
        int gap = UIUtils.dip2px(getContext(),10);
        mPaint.setColor(Color.argb(255, 150, 150, 150));
        mPaint.setTextSize(mDesTextSize);
        Rect desBound = new Rect();
        mPaint.getTextBounds(mDes, 0, mDes.length(), desBound);
        canvas.drawText(mDes, textStartX, titleBound.height() 
                                        + desBound.height() + gap + getPaddingTop(), mPaint);
        if (mIsNeedTimeStamp) {
            //时间戳
            Rect timeBound = new Rect();
            mPaint.setTextSize(UIUtils.dip2px(getContext(), 11));
            mPaint.getTextBounds(mDes, 0, mDes.length(), timeBound);

            canvas.drawText(TimeUtils.getStandarlizdTime(getContext(), mTimeStamp)
                    , getWidth() - timeBound.width(), getHeight() - getPaddingBottom(), mPaint);
        }
        if (mIsNeedStar) {
            //画出star
            if (mScore > 0) {
                int starFullNum = mScore / 2;
                int starhalfNum = mScore % 2;
                int starEmptyNum = 5 - starFullNum - starhalfNum;
                int starDrawX = (int) textStartX;
                for (int count = 0; count < 5; count++) {
                    Drawable drawableStar;
                    if (starFullNum > count)
                        drawableStar = getResources().getDrawable(R.drawable.ic_star_full);
                    else if (starhalfNum != 0 && mScore >= count * 2)
                        drawableStar = getResources().getDrawable(R.drawable.ic_star_half);
                    else
                        drawableStar = getResources().getDrawable(R.drawable.ic_star_empty);
                    drawableStar.setBounds(starDrawX, getHeight() - (drawableStar.getIntrinsicHeight() / 3) - getPaddingBottom(),
                            starDrawX + (drawableStar.getIntrinsicWidth()) / 3, getHeight() - getPaddingBottom());
                    drawableStar.draw(canvas);
                    Log.d(TAG, "height: " + drawableStar.getIntrinsicHeight() + "width: " + drawableStar.getIntrinsicWidth());
                    starDrawX += (drawableStar.getIntrinsicWidth()) / 3 + UIUtils.dip2px(getContext(), 2); //间隔5dp
                }
            }
        }
    }


 
 

Github 地址。

https://github.com/WalkerLiuFei/QingTingFMView 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值