Android自定义指示器时间轴效果实例代码详解
指示器时间轴在外卖、购物类的app里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过listview就可以实现。
在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自定义指示器时间轴效果实例代码详解,希望对大家有所帮助