1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Android开发笔记之自定义控件(物流时间轴的实现)

Android开发笔记之自定义控件(物流时间轴的实现)

时间:2019-05-22 00:21:53

相关推荐

Android开发笔记之自定义控件(物流时间轴的实现)

最近修改项目遇到查看物流这个需求,经过一个下午的时间的终于搞定,趁着这个时间点,赶快把这个功能抽取出来,方便大家以后开发的需要,帮助到更多的人

先看效果图,如下

看完之后,分析可知道,主要是两部分,一个头部和一个body.

那我们最主要的工作就是body内容的实现,头部的实现简单,这里就不再详细的说明

这里我给大家提供一个github上的开源项目,不过这个实现起来,绘制的效果比较慢,不过也可以实现相同的效果

github作者的博客地址

接下来我们就详细的讲解我的实现于哪里

首先我们自定义个类继承自LinearLayout控件,

继承几个构造方法

public class UnderLineLinearLayout extends LinearLayout{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);}

我们看时间轴,可以分析得到,原点分为绿色和灰色两种状态,字体也是如此

初始化一些参数和使用工具

//=============================================================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 locationprivate int lineMarginSide;private int lineDynamicDimen;//line propertyprivate int lineStrokeWidth;private int lineColor;//point propertyprivate int pointSize;private int pointColor;//=============================================================paintprivate 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 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 locationprivate int lineMarginSide;private int lineDynamicDimen;//line propertyprivate int lineStrokeWidth;private int lineColor;//point propertyprivate int pointSize;private int pointColor;//=============================================================paintprivate 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_v_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.point);// mIcon = BitmapFactory.decodeResource(context.getResources(), iconRes);Drawable temp = context.getResources().getDrawable(iconRes);if (drawableToBitmap(temp)!=null) mIcon=drawableToBitmap(temp);// BitmapDrawable bd = (BitmapDrawable) temp;// Bitmap bm = bd.getBitmap();// if (bm != null) mIcon = bm;curOrientation = getOrientation();attr.recycle();setWillNotDraw(false);initView(context);}public static Bitmap drawableToBitmap(Drawable drawable) {Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());drawable.draw(canvas);return bitmap;}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);}@Overrideprotected 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个,也就是第一个和第二个之间连成线,第一个和最后一个分别有点/iconif (childCount > 1) {switch (curOrientation) {case VERTICAL:drawFirstChildViewVertical(canvas);drawLastChildViewVertical(canvas);drawBetweenLineVertical(canvas,childCount);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 Drawprivate void drawFirstChildViewVertical(Canvas canvas) {if (getChildAt(0) != null) {int top = getChildAt(0).getTop();//记录值lastX = (sideRelative>=rootMiddle?(sideRelative-lineMarginSide):(sideRelative+lineMarginSide)) - (mIcon.getWidth() >> 1);lastY = top + getChildAt(0).getPaddingTop() + lineDynamicDimen;//画一个图canvas.drawBitmap(mIcon, lastX, lastY, null);}}private void drawLastChildViewVertical(Canvas canvas) {if (getChildAt(getChildCount()-1) != null) {int top = getChildAt(getChildCount()-1).getTop();//记录值firstX = sideRelative>=rootMiddle?(sideRelative-lineMarginSide):(sideRelative+lineMarginSide);firstY = top + getChildAt(getChildCount()-1).getPaddingTop() + lineDynamicDimen;//画一个圆canvas.drawCircle(firstX, firstY, pointSize, pointPaint);}}private void drawBetweenLineVertical(Canvas canvas, int childCount) {//画剩下的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);}// if (i==0){canvas.drawLine(firstX, firstY, firstX, lastY+mIcon.getHeight(), linePaint);//// }else {//canvas.drawLine(firstX, firstY, firstX, lastY, linePaint);// }}}//=============================================================Horizontal Drawprivate 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@Overridepublic 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();}}

同时还有一个style需要你添加

<!-- 时间轴 --><declare-styleable name="UnderLineLinearLayout"><!--时间轴偏移值--><attr name="line_margin_side" format="dimension"/><!--时间轴动态调整值--><attr name="line_dynamic_dimen" format="dimension"/><!--线宽--><attr name="line_stroke_width" format="dimension"/><!--线的颜色--><attr name="line_v_color" format="color"/><!--点的大小--><attr name="point_size" format="dimension"/><!--点的颜色--><attr name="point_color" format="color"/><!--图标--><attr name="icon_src" format="reference"/><!--时间轴的gravity--><!--the gravity of the timeline--><attr name="line_gravity"><enum name="Left" value="2"/><enum name="Right" value="4"/><enum name="Middle" value="0"/><enum name="Top" value="1"/><enum name="Bottom" value="3"/></attr></declare-styleable>

中间又一个R.drawable.point,就是节点颜色的一个xml,你自己随便定义一个就好

使用的话布局文件如下

<ScrollView android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="none"><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="45dp"android:paddingTop="20px"android:paddingBottom="20px"android:orientation="vertical"android:background="@color/white"><TextViewandroid:id="@+id/txt_logistics_status"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:textSize="@dimen/text_normal_medium"android:textColor="@color/xml_color_text_normal_black"android:text="物流状态: "/><TextViewandroid:id="@+id/txt_logistics_company"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_marginTop="10px"android:gravity="center"android:textSize="@dimen/text_normal_medium"android:textColor="@color/xml_color_text_normal_gray"android:text="承运公司: "/><TextViewandroid:id="@+id/txt_logistics_order_id"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_marginTop="10px"android:gravity="center"android:textSize="@dimen/text_normal_medium"android:textColor="@color/xml_color_text_normal_gray"android:text="运单编号: "/><TextViewandroid:id="@+id/txt_logistics_phone"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_marginTop="10px"android:gravity="center"android:textSize="@dimen/text_normal_medium"android:textColor="@color/xml_color_text_normal_gray"android:text="官方电话: "/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="@color/xml_color_text_normal_gray_cd"/><Viewandroid:layout_width="match_parent"android:layout_height="@dimen/space_normal_dp"android:background="@color/xml_color_text_normal_gray_bg"/><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="@color/xml_color_text_normal_gray_cd"/><UnderLineLinearLayoutandroid:id="@+id/underline_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="@android:color/white"app:line_margin_side="35dp"app:point_size="@dimen/space_6"app:line_stroke_width="@dimen/space_3"app:point_color="@color/xml_color_text_normal_gray_bg"app:line_v_color="@color/xml_color_text_normal_gray_bg"app:line_dynamic_dimen="8dp"/></LinearLayout></ScrollView>

//初始化物流时间轴private void initBody(List<ExpressInfoEntity.ResultBean.ListBean> list){for (int i = 0; i < list.size(); i++) {View v = LayoutInflater.from(this).inflate(R.layout.logicst_item, underlineLayout, false);((TextView) v.findViewById(R.id.tx_action)).setText(list.get(i).getStatus());((TextView) v.findViewById(R.id.tx_time)).setText(list.get(i).getTime());if (i==0){((TextView) v.findViewById(R.id.tx_action)).setTextColor(ContextCompat.getColor(this,R.color.xml_color_text_normal_style));((TextView) v.findViewById(R.id.tx_time)).setTextColor(ContextCompat.getColor(this,R.color.xml_color_text_normal_style));}underlineLayout.addView(v);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。