首先我們來看看效果圖
接下來具體代碼實作,本人不善講解,故所有邏輯都在代碼中 請關注代碼吧。
/**
* 簡易帶有時間軸的linearlayout
*/
public class UnderLineLinearLayout extends LinearLayout {
//=============================================================line gravity常量定義
public static final int GRAVITY_LEFT = 2;
public static final int GRAVITY_RIGHT = 4;
public static final int GRAVITY_MIDDLE = 0;
public static final int GRAVITY_TOP = 1;
public static final int GRAVITY_BOTTOM = 3;
//=============================================================元素定義
private Bitmap mIcon;
//line location
private int lineMarginSide;
private int lineDynamicDimen;
//line property
private int lineStrokeWidth;
private int lineColor;
//point property
private int pointSize;
private int pointColor;
//=============================================================paint
private Paint linePaint;
private Paint pointPaint;
//=============================================================其他輔助參數
//第一個點的位置
private int firstX;
private int firstY;
//最後一個圖的位置
private int lastX;
private int lastY;
//預設垂直
private int curOrientation = VERTICAL;
//line gravity(預設垂直的左邊)
private int lineGravity = GRAVITY_LEFT;
private Context mContext;
//開關
private boolean drawLine = true;
private int rootLeft;
private int rootMiddle;
private int rootRight;
private int rootTop;
private int rootBottom;
//參照點
private int sideRelative;
public UnderLineLinearLayout(Context context) {
this(context, null);
}
public UnderLineLinearLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public UnderLineLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.UnderLineLinearLayout);
lineMarginSide = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_margin_side, 10);
lineDynamicDimen = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_dynamic_dimen, 0);
lineStrokeWidth = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_stroke_width, 2);
lineColor = attr.getColor(R.styleable.UnderLineLinearLayout_line_color, 0xff3dd1a5);
pointSize = attr.getDimensionPixelSize(R.styleable.UnderLineLinearLayout_point_size, 8);
pointColor = attr.getColor(R.styleable.UnderLineLinearLayout_point_color, 0xff3dd1a5);
lineGravity = attr.getInt(R.styleable.UnderLineLinearLayout_line_gravity, GRAVITY_LEFT);
int iconRes = attr.getResourceId(R.styleable.UnderLineLinearLayout_icon_src, R.drawable.spot);
BitmapDrawable temp = null;
if (iconRes != 0) {
temp = (BitmapDrawable) context.getResources().getDrawable(iconRes);
}
if (temp != null) {
mIcon = temp.getBitmap();
}
curOrientation = getOrientation();
attr.recycle();
setWillNotDraw(false);
initView(context);
}
private void initView(Context context) {
this.mContext = context;
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setDither(true);
linePaint.setColor(lineColor);
linePaint.setStrokeWidth(lineStrokeWidth);
linePaint.setStyle(Paint.Style.FILL_AND_STROKE);
pointPaint = new Paint();
pointPaint.setAntiAlias(true);
pointPaint.setDither(true);
pointPaint.setColor(pointColor);
pointPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
calculateSideRelative();
if (drawLine) {
drawTimeLine(canvas);
}
}
private void calculateSideRelative() {
rootLeft = getLeft();
rootTop = getTop();
rootRight = getRight();
rootBottom = getBottom();
if (curOrientation == VERTICAL) rootMiddle = (rootLeft + rootRight) >> 1;
if (curOrientation == HORIZONTAL) rootMiddle = (rootTop + rootBottom) >> 1;
boolean isCorrect = (lineGravity == GRAVITY_MIDDLE || (lineGravity + curOrientation) % 2 != 0);
if (isCorrect) {
switch (lineGravity) {
case GRAVITY_TOP:
sideRelative = rootTop;
break;
case GRAVITY_BOTTOM:
sideRelative = rootBottom;
break;
case GRAVITY_LEFT:
sideRelative = rootLeft;
break;
case GRAVITY_RIGHT:
sideRelative = rootRight;
break;
case GRAVITY_MIDDLE:
sideRelative = rootMiddle;
break;
}
} else {
sideRelative = 0;
}
}
private void drawTimeLine(Canvas canvas) {
int childCount = getChildCount();
if (childCount > 0) {
//大于1,證明至少有2個,也就是第一個和第二個之間連成線,第一個和最後一個分别有點/icon
if (childCount > 1) {
switch (curOrientation) {
case VERTICAL:
drawFirstChildViewVertical(canvas);
drawLastChildViewVertical(canvas);
drawBetweenLineVertical(canvas);
break;
case HORIZONTAL:
drawFirstChildViewHorizontal(canvas);
drawLastChildViewHorizontal(canvas);
drawBetweenLineHorizontal(canvas);
break;
default:
break;
}
} else if (childCount == 1) {
switch (curOrientation) {
case VERTICAL:
drawFirstChildViewVertical(canvas);
break;
case HORIZONTAL:
drawFirstChildViewHorizontal(canvas);
break;
default:
break;
}
}
}
}
//=============================================================Vertical Draw
private void drawFirstChildViewVertical(Canvas canvas) {
if (getChildAt(0) != null) {
int top = getChildAt(0).getTop();
//記錄值
firstX = sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide);
firstY = top + getChildAt(0).getPaddingTop() + lineDynamicDimen;
//畫一個圓
canvas.drawCircle(firstX, firstY, pointSize, pointPaint);
}
}
private void drawLastChildViewVertical(Canvas canvas) {
if (getChildAt(getChildCount() - 1) != null) {
int top = getChildAt(getChildCount() - 1).getTop();
//記錄值
lastX = (sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide)) - (mIcon
.getWidth() >> 1);
lastY = top + getChildAt(getChildCount() - 1).getPaddingTop() + lineDynamicDimen;
//畫一個圖
canvas.drawBitmap(mIcon, lastX, lastY, null);
}
}
private void drawBetweenLineVertical(Canvas canvas) {
//畫剩下的
canvas.drawLine(firstX, firstY, firstX, lastY, linePaint);
for (int i = 0; i < getChildCount() - 1; i++) {
//畫了線,就畫圓
if (getChildAt(i) != null && i != 0) {
int top = getChildAt(i).getTop();
//記錄值
int Y = top + getChildAt(i).getPaddingTop() + lineDynamicDimen;
canvas.drawCircle(firstX, Y, pointSize, pointPaint);
}
}
}
//=============================================================Horizontal Draw
private void drawFirstChildViewHorizontal(Canvas canvas) {
if (getChildAt(0) != null) {
int left = getChildAt(0).getLeft();
//記錄值
firstX = left + getChildAt(0).getPaddingLeft() + lineDynamicDimen;
firstY = sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide);
//畫一個圓
canvas.drawCircle(firstX, firstY, pointSize, pointPaint);
}
}
private void drawLastChildViewHorizontal(Canvas canvas) {
if (getChildAt(getChildCount() - 1) != null) {
int left = getChildAt(getChildCount() - 1).getLeft();
//記錄值
lastX = left + getChildAt(getChildCount() - 1).getPaddingLeft() + lineDynamicDimen;
lastY = (sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide)) - (mIcon
.getWidth() >> 1);
//畫一個圖
canvas.drawBitmap(mIcon, lastX, lastY, null);
}
}
private void drawBetweenLineHorizontal(Canvas canvas) {
//畫剩下的線
canvas.drawLine(firstX, firstY, lastX, firstY, linePaint);
for (int i = 0; i < getChildCount() - 1; i++) {
//畫了線,就畫圓
if (getChildAt(i) != null && i != 0) {
int left = getChildAt(i).getLeft();
//記錄值
int x = left + getChildAt(i).getPaddingLeft() + lineDynamicDimen;
canvas.drawCircle(x, firstY, pointSize, pointPaint);
}
}
}
//=============================================================Getter/Setter
@Override
public void setOrientation(int orientation) {
super.setOrientation(orientation);
this.curOrientation = orientation;
invalidate();
}
public int getLineStrokeWidth() {
return lineStrokeWidth;
}
public void setLineStrokeWidth(int lineStrokeWidth) {
this.lineStrokeWidth = lineStrokeWidth;
invalidate();
}
public boolean isDrawLine() {
return drawLine;
}
public void setDrawLine(boolean drawLine) {
this.drawLine = drawLine;
invalidate();
}
public Paint getLinePaint() {
return linePaint;
}
public void setLinePaint(Paint linePaint) {
this.linePaint = linePaint;
invalidate();
}
public int getPointSize() {
return pointSize;
}
public void setPointSize(int pointSize) {
this.pointSize = pointSize;
invalidate();
}
public int getPointColor() {
return pointColor;
}
public void setPointColor(int pointColor) {
this.pointColor = pointColor;
invalidate();
}
public Paint getPointPaint() {
return pointPaint;
}
public void setPointPaint(Paint pointPaint) {
this.pointPaint = pointPaint;
invalidate();
}
public int getLineColor() {
return lineColor;
}
public void setLineColor(int lineColor) {
this.lineColor = lineColor;
invalidate();
}
public int getLineMarginSide() {
return lineMarginSide;
}
public void setLineMarginSide(int lineMarginSide) {
this.lineMarginSide = lineMarginSide;
invalidate();
}
public int getLineDynamicDimen() {
return lineDynamicDimen;
}
public void setLineDynamicDimen(int lineDynamicDimen) {
this.lineDynamicDimen = lineDynamicDimen;
invalidate();
}
public Bitmap getIcon() {
return mIcon;
}
public void setIcon(Bitmap icon) {
mIcon = icon;
}
public void setIcon(int resId) {
if (resId == 0) return;
BitmapDrawable temp = (BitmapDrawable) mContext.getResources().getDrawable(resId);
if (temp != null) mIcon = temp.getBitmap();
invalidate();
}
public int getLineGravity() {
return lineGravity;
}
public void setLineGravity(int lineGravity) {
this.lineGravity = lineGravity;
invalidate();
}
public OnUnderLineLinkListener underLineLinkListener;
public UnderLineLinearLayout build(Context context, OnUnderLineLinkListener underLineLinkListener) {
this.underLineLinkListener = underLineLinkListener;
LayoutInflater rootInflater = LayoutInflater.from(context);
if (underLineLinkListener != null) {
View rootView = rootInflater.inflate(underLineLinkListener.initWidgetsView(), this, false);
addView(rootView);
UnderLineItemViewHold viewHold = underLineLinkListener.initItemViewHold(rootView);
underLineLinkListener.initWidgetsEvent(viewHold);
}
return this;
}
}
用到的時間軸接口
/**
* 時間軸接口
* Created by Home-Pc on 2017/7/18.
*/
public interface OnUnderLineLinkListener<T extends UnderLineItemViewHold> {
int initWidgetsView();
T initItemViewHold(View itemView);
void initWidgetsEvent(T hold);
}
時間軸ViewHold
/**
* 時間軸VIiewHold
* Created by Home-Pc on 2017/7/19.
*/
public abstract class UnderLineItemViewHold {
public UnderLineItemViewHold(View itemView){
}
}
activity需要實作的代碼
public class MyItemViewHold extends UnderLineItemViewHold {
TextView inResultTvShow, inResultTime;
public MyItemViewHold(View itemView) {
super(itemView);
inResultTvShow = (TextView) itemView.findViewById(R.id.inResultTvShow);
inResultTime = (TextView) itemView.findViewById(R.id.inResultTime);
}
}
private void initView(final String contentText, final int textColor, final String timeText, final int timeColor) {
myUnderLineaLinerLayout.build(this, new OnUnderLineLinkListener<MyItemViewHold>() {
@Override
public int initWidgetsView() {
return R.layout.v_investment_result_item_layout;
}
@Override
public UnderLineItemViewHold initItemViewHold(View itemView) {
return new MyItemViewHold(itemView);
}
@Override
public void initWidgetsEvent(MyItemViewHold hold) {
hold.inResultTvShow.setText(contentText == null ? "" : contentText);
hold.inResultTvShow.setTextColor(ContextCompat.getColor(MainActivity.this, textColor));
hold.inResultTime.setText(timeText == null ? "" : timeText);
hold.inResultTime.setTextColor(ContextCompat.getColor(MainActivity.this, timeColor));
}
});
}
activity 調用方法
initView("投資時間", R.color.blackColor, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);