Android RecycleView(四)——时间轴

       上一篇Android RecycleView(三) 完成了点击事件 这次使用recycleview完成一个有意思的时光轴效果。

效果图:


要实现次效果呢 其实就是我们在每一个item中画一个圆圈加一个线的图形


第一种和第二种都可以实现,当然我们可以找美工给我们相应的图片,放入item中,今天我们不说图片,自己画出第一个,第二个原理一样,只是画的坐标不一样。


自定义的 图形:

package com.chs.myrecycleview.widget;

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

import com.chs.myrecycleview.R;

/**
 * 作者:chs on 2016/2/4 10:02
 * 邮箱:657083984@qq.com
 */
public class TimeLine extends View {
    public static final int START = 0;
    public static final int END = 1;
    public static final int NORMAL = 2;
    public static final int SPECIAL = 3;//只有一条数据的时候
    private int mIconSize;
    private int mLineSize;
    private Drawable mBeginLine;
    private Drawable mEndLine;
    private Drawable mIcon;

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

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

    public TimeLine(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.TimeLine);
        this.mBeginLine = array.getDrawable(R.styleable.TimeLine_begin_line);
        this.mEndLine = array.getDrawable(R.styleable.TimeLine_end_line);
        this.mIcon = array.getDrawable(R.styleable.TimeLine_my_icon);
        this.mIconSize = array.getDimensionPixelSize(R.styleable.TimeLine_my_icon_size,20);
        this.mLineSize = array.getDimensionPixelSize(R.styleable.TimeLine_line_size,2);
        array.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int w = mIconSize+getPaddingRight()+getPaddingLeft();
        int h = mIconSize+getPaddingTop() +getPaddingBottom();

        int widthSize = resolveSizeAndState(w,widthMeasureSpec,0);
        int heightSize = resolveSizeAndState(h,heightMeasureSpec,0);
        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //当view显示的时候调用此方法
        initDrawable();
    }

    private void initDrawable() {
        int left = getPaddingLeft();
        int right = getPaddingRight();
        int top = getPaddingTop();
        int bottom = getPaddingBottom();

        int width = getWidth();
        int height = getHeight();
        int cWidth = width-left-right;
        int cHeight = height-top-bottom;
        int iconSize = Math.min(mIconSize,Math.min(cWidth,cHeight));
        Rect bounds = null;
        if(mIcon!=null){
            mIcon.setBounds(left,top,left+iconSize,top+iconSize);
            bounds = mIcon.getBounds();

        }
        int lineLeft = bounds.centerX() - mLineSize/2;//除以2
        if(mBeginLine!=null){
            mBeginLine.setBounds(lineLeft,0,lineLeft+mLineSize,bounds.top);
        }
        if(mEndLine!=null){
            mEndLine.setBounds(lineLeft,bounds.bottom,lineLeft+mLineSize,height);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        if(mBeginLine!=null){
//            mBeginLine.draw(canvas);
//        }
        if(mEndLine!=null){
            mEndLine.draw(canvas);
        }
        if(mIcon!=null){
            mIcon.draw(canvas);
        }
    }

    public void setIconSize(int mIconSize) {
        this.mIconSize = mIconSize;
        initDrawable();
        invalidate();
    }

    public void setLineSize(int mLineSize) {
        this.mLineSize = mLineSize;
        initDrawable();
        invalidate();
    }

    public void setBeginLine(Drawable mBeginLine) {
        this.mBeginLine = mBeginLine;
        initDrawable();
        invalidate();
    }

    public void setEndLine(Drawable mEndLine) {
        this.mEndLine = mEndLine;
        initDrawable();
        invalidate();
    }

    public void setIcon(Drawable mIcon) {
        this.mIcon = mIcon;
        initDrawable();
        invalidate();
    }
}

item中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myApp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:id="@+id/ll_main"
    >
    <com.chs.myrecycleview.widget.TimeLine
        android:id="@+id/time_line"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="10dp"
        myApp:my_icon="@drawable/cicle"
        myApp:my_icon_size="25dp"
        myApp:begin_line="@drawable/line"
        myApp:end_line="@drawable/line"
        myApp:line_size="3dp"
        />
    <TextView
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="10dp"
        android:textSize="20sp"
        android:text="hahah"
        />
</LinearLayout>

自定义属性 :定义圆和线的宽高:这里是按照上面图二中写的 分了3部分 画的时候没用到beginline

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="TimeLine">
        <attr name="begin_line" format="color|reference"/>
        <attr name="end_line" format="color|reference"/>
        <attr name="line_size" format="dimension"/>
        <attr name="my_icon_size" format="dimension"/>
        <attr name="my_icon" format="color|reference"/>
    </declare-styleable>
</resources>



在drawable中定义两个shape 一个圆形 一个方形

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorPrimary" />
</shape>

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/colorPrimary" />
</shape>



然后我们把上一篇的item中的线条去掉即可。


更新一下现在用的新的 。因为我发现这个东西就一个圆圈两个线条  根本不用绘制图片 直接canvas画就好了 然后重新写了一个 不需要再写shape 和自定义属性:

package com.hsm.bxt.widgets;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import com.hsm.bxt.utils.DensityUtil;

/**
 * 作者:chs on 2016/10/21 10:56
 * 邮箱:657083984@qq.com
 */

public class PatrolPointMarker extends View {
    private Paint mCirclePaint, mLinePaint,mTextPaint;
    private int mCircleColor = Color.parseColor("#C4D4E8");
    private int mLineColor = Color.parseColor("#C4D4E8");
    private int mTextColor = Color.parseColor("#ffffff");
    private int mRadius = 36;
    private int mToLineHeight;
    private int mLineHeight;
    private String mText = "001";
    private boolean mIsDrawTopLine = true;
    private boolean mIsDrawBottomLine = true;
    public PatrolPointMarker(Context context) {
        super(context);
        init(context);
    }

    public PatrolPointMarker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PatrolPointMarker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        int mWidth = context.getResources().getDisplayMetrics().widthPixels;
        mRadius = (int)mWidth/30;
        mToLineHeight = DensityUtil.dip2px(context,5);
        int strokeWidth = DensityUtil.dip2px(context, 2);
        int textSize = DensityUtil.dip2px(context, 10);
        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setColor(mCircleColor);

        mLinePaint = new Paint();
        mLinePaint.setAntiAlias(true);
        mLinePaint.setStrokeWidth(strokeWidth);
        mLinePaint.setColor(mLineColor);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(textSize);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int desiredWidth = mRadius*2;
        int desiredHeight = getPaddingBottom()+getPaddingTop();
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        //计算宽度
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            width = Math.min(desiredWidth, widthSize);
        } else {
            width = desiredWidth;
        }
        //计算高度
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            height = Math.min(desiredHeight, heightSize);
        } else {
            height = desiredHeight;
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mLineHeight = h-mRadius*2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(mIsDrawTopLine){
            canvas.drawLine(mRadius,0,mRadius,mToLineHeight,mLinePaint);
        }
        canvas.drawCircle(mRadius,mRadius+mToLineHeight,mRadius,mCirclePaint);
        if(mIsDrawBottomLine){
        canvas.drawLine(mRadius,mRadius*2+mToLineHeight,mRadius,mRadius*2+mToLineHeight+mLineHeight,mLinePaint);
        }
        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        int baseline = (mRadius*2+mToLineHeight*2 - fontMetrics.bottom - fontMetrics.top) / 2;
        canvas.drawText(mText,mRadius-mTextPaint.measureText(mText)/2,baseline,mTextPaint);
    }
    public void setText(String text){
        this.mText = text;
        invalidate();
    }
    public void setDrawTopLine(boolean drawTopLine){
        this.mIsDrawTopLine = drawTopLine;
    }
    public void setDrawBottomLine(boolean drawBottomLine){
        this.mIsDrawBottomLine = drawBottomLine;
    }

    public void setCircleColor(int color){
        mCirclePaint.setColor(color);
        invalidate();
    }

    public void setLineColor(int color){
        mLinePaint.setColor(color);
        invalidate();
    }
}



package com.hsm.bxt.utils;

import android.content.Context;

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



就一百多行代码 非常轻量,用起来更方便。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值