iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何在Android中利用View实现一个垂直时间轴布局
  • 340
分享到

如何在Android中利用View实现一个垂直时间轴布局

androidviewroi 2023-05-31 09:05:25 340人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关如何在Android中利用View实现一个垂直时间轴布局,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。时间轴,顾名思义就是将发生的事件按照时间顺序罗列起来,给用户

这篇文章将为大家详细讲解有关如何在Android中利用View实现一个垂直时间轴布局,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

时间轴,顾名思义就是将发生的事件按照时间顺序罗列起来,给用户带来一种更加直观的体验。

分析

实现这个最常用的一个方法就是用ListView,我这里用继承LinearLayout的方式来实现。首先定义了一些自定义属性:

attrs.xml

<?xml version="1.0" encoding="utf-8"?> <resources>   <declare-styleable name="TimelineLayout">     <!--时间轴左偏移值-->     <attr name="line_margin_left" fORMat="dimension"/>     <!--时间轴上偏移值-->     <attr name="line_margin_top" format="dimension"/>     <!--线宽-->     <attr name="line_stroke_width" format="dimension"/>     <!--线的颜色-->     <attr name="line_color" format="color"/>     <!--点的大小-->     <attr name="point_size" format="dimension"/>     <!--点的颜色-->     <attr name="point_color" format="color"/>     <!--图标-->     <attr name="icon_src" format="reference"/>   </declare-styleable> </resources>

TimelineLayout.java

package com.jackie.timeline;  import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.canvas; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout;    public class TimelineLayout extends LinearLayout {   private Context mContext;    private int mLineMarginLeft;   private int mLineMarginTop;   private int mLineStrokeWidth;   private int mLineColor;;   private int mPointSize;   private int mPointColor;   private Bitmap mIcon;    private Paint mLinePaint; //线的画笔   private Paint mPointPaint; //点的画笔       //第一个点的位置   private int mFirstX;   private int mFirstY;   //最后一个图标的位置   private int mLastX;   private int mLastY;    public TimelineLayout(Context context) {     this(context, null);   }    public TimelineLayout(Context context, @Nullable AttributeSet attrs) {     this(context, attrs, 0);   }    public TimelineLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TimelineLayout);     mLineMarginLeft = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_margin_left, 10);     mLineMarginTop = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_margin_top, 0);     mLineStrokeWidth = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_stroke_width, 2);     mLineColor = ta.getColor(R.styleable.TimelineLayout_line_color, 0xff3Dd1a5);     mPointSize = ta.getDimensionPixelSize(R.styleable.TimelineLayout_point_size, 8);     mPointColor = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_point_color, 0xff3dd1a5);      int iconRes = ta.getResourceId(R.styleable.TimelineLayout_icon_src, R.drawable.ic_ok);     BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(iconRes);     if (drawable != null) {       mIcon = drawable.getBitmap();     }      ta.recycle();      setWillNotDraw(false);     initView(context);   }    private void initView(Context context) {     this.mContext = context;      mLinePaint = new Paint();     mLinePaint.setAntiAlias(true);     mLinePaint.setDither(true);     mLinePaint.setColor(mLineColor);     mLinePaint.setStrokeWidth(mLineStrokeWidth);     mLinePaint.setStyle(Paint.Style.FILL_AND_STROKE);      mPointPaint = new Paint();     mPointPaint.setAntiAlias(true);     mPointPaint.setDither(true);     mPointPaint.setColor(mPointColor);     mPointPaint.setStyle(Paint.Style.FILL);   }    @Override   protected void onDraw(Canvas canvas) {     super.onDraw(canvas);          drawTimeline(canvas);   }    private void drawTimeline(Canvas canvas) {     int childCount = getChildCount();      if (childCount > 0) {       if (childCount > 1) {         //大于1,证明至少有2个,也就是第一个和第二个之间连成线,第一个和最后一个分别有点和icon         drawFirstPoint(canvas);         drawLastIcon(canvas);         drawBetweenLine(canvas);       } else if (childCount == 1) {         drawFirstPoint(canvas);       }     }   }    private void drawFirstPoint(Canvas canvas) {     View child = getChildAt(0);     if (child != null) {       int top = child.getTop();       mFirstX = mLineMarginLeft;       mFirstY = top + child.getPaddingTop() + mLineMarginTop;        //画圆       canvas.drawCircle(mFirstX, mFirstY, mPointSize, mPointPaint);     }   }    private void drawLastIcon(Canvas canvas) {     View child = getChildAt(getChildCount() - 1);     if (child != null) {       int top = child.getTop();       mLastX = mLineMarginLeft;       mLastY = top + child.getPaddingTop() + mLineMarginTop;        //画图       canvas.drawBitmap(mIcon, mLastX - (mIcon.getWidth() >> 1), mLastY, null);     }   }    private void drawBetweenLine(Canvas canvas) {     //从开始的点到最后的图标之间,画一条线     canvas.drawLine(mFirstX, mFirstY, mLastX, mLastY, mLinePaint);     for (int i = 0; i < getChildCount() - 1; i++) {       //画圆       int top = getChildAt(i).getTop();       int y = top + getChildAt(i).getPaddingTop() + mLineMarginTop;       canvas.drawCircle(mFirstX, y, mPointSize, mPointPaint);     }   }    public int getLineMarginLeft() {     return mLineMarginLeft;   }    public void setLineMarginLeft(int lineMarginLeft) {     this.mLineMarginLeft = lineMarginLeft;     invalidate();   } }

从上面的代码可以看出,分三步绘制,首先绘制开始的实心圆,然后绘制结束的图标,然后在开始和结束之间先绘制一条线,然后在线上在绘制每个步骤的实心圆。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"   xmlns:app="http://schemas.android.com/apk/res-auto"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:orientation="vertical">    <LinearLayout     android:layout_width="match_parent"     android:layout_height="50dp"     android:weightSum="2">      <Button       android:id="@+id/add_item"       android:layout_width="0dp"       android:layout_height="match_parent"       android:layout_weight="1"       android:text="add"/>      <Button       android:id="@+id/sub_item"       android:layout_width="0dp"       android:layout_height="match_parent"       android:layout_weight="1"       android:text="sub"/>   </LinearLayout>    <LinearLayout     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:orientation="horizontal"     android:weightSum="2">      <Button       android:id="@+id/add_margin"       android:layout_width="0dp"       android:layout_weight="1"       android:layout_height="wrap_content"       android:text="+"/>      <Button       android:id="@+id/sub_margin"       android:layout_width="0dp"       android:layout_weight="1"       android:layout_height="wrap_content"       android:text="-"/>   </LinearLayout>    <TextView     android:id="@+id/current_margin"     android:layout_width="match_parent"     android:layout_height="40dp"     android:gravity="center"     android:text="current line margin left is 25dp"/>    <ScrollView     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:scrollbars="none">      <com.jackie.timeline.TimelineLayout       android:id="@+id/timeline_layout"       android:layout_width="match_parent"       android:layout_height="wrap_content"       app:line_margin_left="25dp"       app:line_margin_top="8dp"       android:orientation="vertical"       android:background="@android:color/white">     </com.jackie.timeline.TimelineLayout>   </ScrollView> </LinearLayout>

MainActivity.java

package com.jackie.timeline;  import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.TextView;  public class MainActivity extends AppCompatActivity implements View.OnClickListener {   private Button addItemButton;   private Button subItemButton;   private Button addMarginButton;   private Button subMarginButton;   private TextView mCurrentMargin;    private TimelineLayout mTimelineLayout;    @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      initView();   }    private void initView() {     addItemButton = (Button) findViewById(R.id.add_item);     subItemButton = (Button) findViewById(R.id.sub_item);     addMarginButton= (Button) findViewById(R.id.add_margin);     subMarginButton= (Button) findViewById(R.id.sub_margin);     mCurrentMargin= (TextView) findViewById(R.id.current_margin);     mTimelineLayout = (TimelineLayout) findViewById(R.id.timeline_layout);      addItemButton.setOnClickListener(this);     subItemButton.setOnClickListener(this);     addMarginButton.setOnClickListener(this);     subMarginButton.setOnClickListener(this);   }    private int index = 0;   private void addItem() {     View view = LayoutInflater.from(this).inflate(R.layout.item_timeline, mTimelineLayout, false);     ((TextView) view.findViewById(R.id.tv_action)).setText("步骤" + index);     ((TextView) view.findViewById(R.id.tv_action_time)).setText("2017年3月8日16:55:04");     ((TextView) view.findViewById(R.id.tv_action_status)).setText("完成");     mTimelineLayout.addView(view);     index++;   }    private void subItem() {     if (mTimelineLayout.getChildCount() > 0) {       mTimelineLayout.removeViews(mTimelineLayout.getChildCount() - 1, 1);       index--;     }   }    @Override   public void onClick(View v) {     switch (v.getId()){       case R.id.add_item:         addItem();         break;       case R.id.sub_item:         subItem();         break;       case R.id.add_margin:         int currentMargin = UIHelper.pxToDip(this, mTimelineLayout.getLineMarginLeft());         mTimelineLayout.setLineMarginLeft(UIHelper.dipToPx(this, ++currentMargin));         mCurrentMargin.setText("current line margin left is " + currentMargin + "dp");         break;       case R.id.sub_margin:         currentMargin = UIHelper.pxToDip(this, mTimelineLayout.getLineMarginLeft());         mTimelineLayout.setLineMarginLeft(UIHelper.dipToPx(this, --currentMargin));         mCurrentMargin.setText("current line margin left is " + currentMargin + "dp");         break;       default:         break;     }   } }

item_timeline.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:paddingLeft="65dp"   android:paddingTop="20dp"   android:paddingRight="20dp"   android:paddingBottom="20dp">    <TextView     android:id="@+id/tv_action"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:textSize="14sp"     android:textColor="#1a1a1a"     android:text="测试一"/>    <TextView     android:id="@+id/tv_action_time"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:textSize="12sp"     android:textColor="#8e8e8e"     android:layout_below="@id/tv_action"     android:layout_marginTop="10dp"     android:text="2017年3月8日16:49:12"/>    <TextView     android:id="@+id/tv_action_status"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:textSize="14sp"     android:textColor="#3dd1a5"     android:layout_alignParentRight="true"     android:text="完成"/>  </RelativeLayout>

附上像素工具转化的工具类:

package com.jackie.timeline;  import android.content.Context;   public final class UIHelper {    private UIHelper() throws InstantiationException {     throw new InstantiationException("This class is not for instantiation");   }       public static int dipToPx(Context context, float dip) {     return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f);   }       public static int pxToDip(Context context, float pxValue) {     final float scale = context.getResources().getDisplayMetrics().density;     return (int) (pxValue / scale + 0.5f);   } }

关于如何在Android中利用View实现一个垂直时间轴布局就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: 如何在Android中利用View实现一个垂直时间轴布局

本文链接: https://www.lsjlt.com/news/224796.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何在Android中利用View实现一个垂直时间轴布局
    这篇文章将为大家详细讲解有关如何在Android中利用View实现一个垂直时间轴布局,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。时间轴,顾名思义就是将发生的事件按照时间顺序罗列起来,给用户...
    99+
    2023-05-31
    android view roi
  • 如何在Android应用中利用ViewFlipper实现一个垂直滚动广告条
    这篇文章给大家介绍如何在Android应用中利用ViewFlipper实现一个垂直滚动广告条,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、ViewFlipper的布局实现布局的编写很简单,跟普通布局一样的<&...
    99+
    2023-05-31
    android viewflipper pp
  • Android中怎么实现一个简易时间轴
    这期内容当中小编将会给大家带来有关Android中怎么实现一个简易时间轴,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。新建一个自定义控件:public class WorkExcVie...
    99+
    2023-05-30
    android
  • Android开发中使用View实现一个垂直上拉下滑功能
    Android开发中使用View实现一个垂直上拉下滑功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。效果二、实现思路 这个效果其实有很多实现方法,为了让松手时...
    99+
    2023-05-31
    android view roi
  • 如何在Android中利用itemdecoration实现一个时间线效果
    今天就跟大家聊聊有关如何在Android中利用itemdecoration实现一个时间线效果,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。代码如下:// 时间线装饰器pub...
    99+
    2023-06-06
  • 怎么在Android应用中利用onTouchEvent实现一个滑动布局
    本篇文章给大家分享的是有关怎么在Android应用中利用onTouchEvent实现一个滑动布局,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。boolean onTouch(V...
    99+
    2023-05-31
    android ontouchevent roi
  • 如何在Android中利用view实现一个手势密码功能
    这篇文章将为大家详细讲解有关如何在Android中利用view实现一个手势密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。用法: <com.leo.library.view.Ge...
    99+
    2023-05-31
    android roi view
  • 怎么在Android应用中利用View实现一个倒计时功能
    这篇文章将为大家详细讲解有关怎么在Android应用中利用View实现一个倒计时功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Android 自定义View实现倒计时需求:具体方法如下:...
    99+
    2023-05-31
    android roi view
  • 如何在android中利view实现一个推箱子小游戏
    如何在android中利view实现一个推箱子小游戏?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。自定义view:package com.jisai.materialdes...
    99+
    2023-05-31
    android view roi
  • 如何在Android中利用View实现一个等级滑动条功能
    这篇文章将为大家详细讲解有关如何在Android中利用View实现一个等级滑动条功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。思路: 首先绘制直线,然后等分直线绘制点; 绘制点...
    99+
    2023-05-31
    android view roi
  • android应用中怎么利用onLayout()实现一个流式布局
    这期内容当中小编将会给大家带来有关android应用中怎么利用onLayout()实现一个流式布局,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在onLayout方法中有四个参数,我画了一个简单的图来分清...
    99+
    2023-05-31
    android roi onlayout()
  • 怎么在Android中利用view实现一个太极效果
    怎么在Android中利用view实现一个太极效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Android自定义view实现太极效果实例代码之前一直想要个加载的load...
    99+
    2023-05-31
    android view roi
  • 如何利用css flex实现垂直居中
    这篇文章主要介绍如何利用css flex实现垂直居中,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 应用flex实现垂直居中 行使css flex完成垂直居中。flex...
    99+
    2024-04-02
  • 如何利用Android从0到1实现一个流布局控件
    小编给大家分享一下如何利用Android从0到1实现一个流布局控件,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!前言流布局在在项目中还是会时不时地用到的,比如在搜索历史记录,分类,热门词语等可用标签来显示的,都可以设计成流...
    99+
    2023-06-20
  • web开发中如何实现水平垂直居中与flexbox布局
    这篇文章主要介绍了web开发中如何实现水平垂直居中与flexbox布局 ,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。行内元素的水平居中要实...
    99+
    2024-04-02
  • 如何利用JS实现时间轴动画效果
    目录css动画什么是时间轴动画?动画对象动画函数思考总结css动画 在前端开发中,一些简单的动效往往是使用 css3 的 @keyframes 来实现的 ,如: .div1 { ...
    99+
    2024-04-02
  • 怎么在Android应用中利用View实现一个旋转功能
    本篇文章为大家展示了怎么在Android应用中利用View实现一个旋转功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。添加右侧旋转Bitmap turnBitmap =&nbs...
    99+
    2023-05-31
    android view roi
  • 如何在Android应用中利用ProgressBar实现一个直线进度条功能
    今天就跟大家聊聊有关如何在Android应用中利用ProgressBar实现一个直线进度条功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java代码:package com.ex...
    99+
    2023-05-31
    android progressbar gr
  • 利用Android从0到1实现一个流布局控件
    目录前言演示效果:实现步骤:核心点:总结前言 流布局在在项目中还是会时不时地用到的,比如在搜索历史记录,分类,热门词语等可用标签来显示的,都可以设计成流布局的展示方式。这里我从0到1...
    99+
    2024-04-02
  • 如何在android应用中利用service实现一个计时器功能
    本篇文章给大家分享的是有关如何在android应用中利用service实现一个计时器功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先建立主页面的设计:activity_t...
    99+
    2023-05-31
    android service roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作