欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义指示器时间轴效果实例代码详解

程序员文章站 2022-07-01 16:20:23
指示器时间轴在外卖、购物类的app里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过listview就可以实现。 在activit...

指示器时间轴在外卖、购物类的app里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过listview就可以实现。

Android自定义指示器时间轴效果实例代码详解

在activity关联的布局文件activity_main.xml中放置一个listview,代码如下。由于这个列表只是用于展示信息,并不需要用户去点击,所以将其clickable属性置为false;为了消除listview点击产生的波纹效果,我们设置其listselector属性的值为透明;我们不需要列表项之间的分割线,所以设置其divider属性的值为null。

activity_main

<listview
  android:id="@+id/lvtrace"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:clickable="false"
  android:divider="@null"
  android:dividerheight="0dp"  android:listselector="@android:color/transparent" />

每个列表项的布局stepview_adapter.xml,代码如下。由于时间轴的点和线都位于item布局中,为了使线是连续的,所以设置上面listview的dividerheight属性值为0dp,即垂直方向每个列表项都是紧挨着的。在item的布局中,我们先使用linearlayout将布局分成左右两个部分,左边就是时间轴的布局,右边是内容的布局。

内容的布局,物流信息是一个relativelayout,为了不使两个列表项的文本靠得太近,在relativelayout中设置其paddingbottom和paddingtop属性。

时间轴的布局,时间轴的布局也是一个relativelayout,为了使时间轴的圆点和显示时间的文本对齐,我们需要在圆点之上再放置一条竖线,所以整体的布局就是 线 - 点 - 线。为了让线可以正好对准圆点的中心,我们让线和点都水平居中,即android:layout_centerhorizontal="true"

stepview_adapter

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:gravity="center"
  android:orientation="horizontal">
  <relativelayout
    android:id="@+id/rltimeline"
    android:layout_width="wrap_content"
    android:layout_marginleft="15dp"
    android:layout_height="match_parent">
    <textview
      android:id="@+id/tvtopline"
      android:layout_width="1.2dp"
      android:layout_height="12dp"
      android:layout_centerhorizontal="true"
      android:background="#999" />
    <textview
      android:id="@+id/tvdot"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_below="@id/tvtopline"
      android:layout_centerhorizontal="true"
      android:background="@drawable/state_get_huankuan" />
    <textview
      android:layout_width="1.2dp"
      android:id="@+id/tvline"
      android:layout_height="match_parent"
      android:layout_below="@id/tvdot"
      android:layout_centerhorizontal="true"
      android:background="#999" />
  </relativelayout>
  <relativelayout
    android:id="@+id/rlcenter"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingbottom="6dp"
    android:paddingright="10dp"
    android:layout_marginleft="20dp"
    android:paddingtop="12dp">
    <textview
      android:id="@+id/step_tv_time"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignparentright="true"
      android:layout_marginright="6dp"
      android:text="10-20 22:22"
      android:textcolor="#cccccc"
      android:textsize="12sp" />
    <textview
      android:id="@+id/step_tv_des"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignparentleft="true"
      android:layout_marginright="15dp"
      android:textstyle="bold"
      android:layout_toleftof="@+id/step_tv_time"
      android:text="fffffff" />
    <textview
      android:id="@+id/step_tv_des_below"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignparentleft="true"
      android:layout_below="@+id/step_tv_des"
      android:layout_margintop="5dp"
      android:text=""
      android:textcolor="#999999" />
  </relativelayout>
</linearlayout><br><br><br>

定义一个adapter,代码如下。由于第一行的物流信息的显示形式和其他的不一样,所以要注意第一行的item的时间轴布局中最上面的线不显示

public class stepviewadapter extends baseadapter {
  private context context;
  private list<stepviewbean> tracelist = new arraylist<>();
  private static final int type_finish = 101;
  private static final int type_unfinish = 102;
  private static final int type_error = 103;
  public stepviewadapter(context context, list<stepviewbean> tracelist) {
    this.context = context;
    this.tracelist = tracelist;
  }
  @override
  public int getcount() {
    return tracelist.size();
  }
  @override
  public stepviewbean getitem(int position) {
    return tracelist.get(position);
  }
  @override
  public long getitemid(int position) {
    return position;
  }
  @override
  public view getview(int position, view convertview, viewgroup parent) {
    viewholder holder;
    final stepviewbean trace = getitem(position);
    if (convertview != null) {
      holder = (viewholder) convertview.gettag();
    } else {
      holder = new viewholder();
      convertview = layoutinflater.from(context).inflate(r.layout.stepview_adapter, parent, false);
      holder.tvtopline = (textview) convertview.findviewbyid(r.id.tvtopline);
      holder.tvdot = (textview) convertview.findviewbyid(r.id.tvdot);
      holder.tvline = (textview) convertview.findviewbyid(r.id.tvline);
      holder.tvacceptstation = (textview) convertview.findviewbyid(r.id.step_tv_des);
      holder.tvaccepttime = (textview) convertview.findviewbyid(r.id.step_tv_time);
      holder.tvacceptstationbelow = (textview) convertview.findviewbyid(r.id.step_tv_des_below);
      holder.rltimeline = (relativelayout) convertview.findviewbyid(rltimeline);
      convertview.settag(holder);
    }
    if (position == 0) {
      holder.tvtopline.setvisibility(view.invisible);
    }
    if (position == tracelist.size() - 1) {
      holder.tvline.setvisibility(view.gone);
    } else {
      holder.tvline.setvisibility(view.visible);
    }
    switch (getitemviewtype(position)) {
      case type_finish:
        holder.tvacceptstation.settextcolor(context.getresources().getcolor(r.color.crt_completed));
        holder.tvdot.setbackgroundresource(r.drawable.state_get_huankuan);
        holder.tvline.setbackgroundcolor(context.getresources().getcolor(r.color.crt_completed));
        holder.tvtopline.setbackgroundcolor(context.getresources().getcolor(r.color.crt_completed));
        break;
      case type_unfinish:
        holder.tvacceptstation.settextcolor(context.getresources().getcolor(r.color.crt_uncompleted_text));
        holder.tvdot.setbackgroundresource(r.drawable.state_normal_huankuan);
        holder.tvline.setbackgroundcolor(context.getresources().getcolor(r.color.crt_text_hint_color));
        break;
      case type_error:
        holder.tvtopline.setvisibility(view.visible);
        holder.tvacceptstation.settextcolor(context.getresources().getcolor(r.color.crt_error_text));
        holder.tvdot.setbackgroundresource(r.drawable.state_lose_huankuan);
        break;
    }
    holder.tvaccepttime.settext(trace.getaccepttime());
    holder.tvacceptstation.settext(trace.getacceptstation());
    if (!textutils.isempty(trace.getacceptstation())) {
      holder.tvacceptstationbelow.settext(trace.getacceptstationbelow());
    }
    return convertview;
  }
  @override
  public int getitemviewtype(int id) {
     if(id==(tracelist.size()-2)){
       return type_error;
     }
     if(id==(tracelist.size()-1)){
       return type_unfinish;
     }
     return type_finish;
  }
  static class viewholder {
    public textview tvaccepttime, tvacceptstation, tvline, tvacceptstationbelow;
    public textview tvtopline, tvdot;
    public relativelayout rltimeline;
  }
}

为了可以看到布局的效果,在activity中模拟一些假数据。需要定义一个实体类trace,它有两个属性,accepttime和acceptstation,代码如下:

stepviewbean

public class stepviewbean {
  /** 时间 */
  private string accepttime;
  /** 描述 */
  private string acceptstation;
  /** 描述下方*/
  private string acceptstationbelow;
  public string getacceptstationbelow() {
    return acceptstationbelow;
  }
  public void setacceptstationbelow(string acceptstationbelow) {
    this.acceptstationbelow = acceptstationbelow;
  }
  public stepviewbean() {
  }
  public stepviewbean(string accepttime, string acceptstation) {
    this.accepttime = accepttime;
    this.acceptstation = acceptstation;
  }
  public stepviewbean(string accepttime, string acceptstation, string acceptstationbelow) {
    this.accepttime = accepttime;
    this.acceptstation = acceptstation;
    this.acceptstationbelow = acceptstationbelow;
  }
  public string getaccepttime() {
    return accepttime;
  }
  public void setaccepttime(string accepttime) {
    this.accepttime = accepttime;
  }
  public string getacceptstation() {
    return acceptstation;
  }
  public void setacceptstation(string acceptstation) {
    this.acceptstation = acceptstation;
  }
} 

mainactivity 

public class mainactivity extends appcompatactivity {
  private list<stepviewbean> tracelist = new arraylist<>();
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    listview lvtrace= (listview) findviewbyid(r.id.lvtrace);
    tracelist.add(new stepviewbean("10-20 22: 22", "您的订单已打印完毕", "招商银行(9979) 小明\n支付金额  100000"));
    tracelist.add(new stepviewbean("10-20 22:22", "您已提交定单,等待系统确认"));
    tracelist.add(new stepviewbean("10-20 22:24", "您的订单已拣货完成"));
    tracelist.add(new stepviewbean("10-20 22:24", "扫描员已经扫描"));
    tracelist.add(new stepviewbean("10-20 22:24", "您的订单已拣货完成"));
    tracelist.add(new stepviewbean("10-20 22:24", "感谢你在京东购物,欢迎你下次光临!"));
    stepviewadapter adapter = new stepviewadapter(this, tracelist);
    lvtrace.setadapter(adapter);
  }
}

 github地址:https://github.com/peiniwan/stepview

总结

以上所述是小编给大家介绍的android自定义指示器时间轴效果实例代码详解,希望对大家有所帮助