最近学习了时间轴的用法,用到了一个左右交叉布局,其间有些东西我觉得可以跟大家分享一下,还是那句话:我是小菜鸟,大家多多指教。

先给大家看下效果图,至于GIF动画,目前还在学习中,后期希望能上传GIF动画,这是正在做的项目中抽取出来的一部分

该时间轴参考了网上很流行的ListView控件制作的,每一行都加载相同的Item布局文件,将divider的高度设置为0,就可以达到效果了。

下面看代码,我喜欢从布局文件开始。

首先是main.xml布局,这个布局没什么好讲的,主要是一个Listview控件,大家可以根据需要添加其他辅助控件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.cjt.timelinedemo.MainActivity" ><ListViewandroid:id="@+id/timeLine"android:layout_width="match_parent"android:layout_height="match_parent"        android:layout_alignParentLeft="true"android:layout_alignParentTop="true" ></ListView></RelativeLayout>

因为是左右交叉的时间轴布局,左右肯定不能复用,所以要创建两个布局文件,分别对应左右的布局视图

如上图,以左侧的时间为区分,分为左右布局,上代码left_list_item.xml

<?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:baselineAligned="false"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_marginRight="3dp"android:gravity="center|right"android:orientation="vertical" ><TextViewandroid:id="@+id/left_tv_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="14sp"android:textStyle="bold"android:text="2016-06-28 17:50" /></LinearLayout><LinearLayoutandroid:layout_width="20dp"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical" ><!-- 上下各画一根橙色的线条,线宽设置为2dp --><Viewandroid:layout_width="2dp"android:layout_height="0dp"android:layout_weight="1" android:background="#FB7F02"/><!-- 设置中间的节点大小为20x20 --><ImageViewandroid:layout_width="20dp"android:layout_height="20dp"android:src="@drawable/item_center_circle" /><Viewandroid:layout_width="2dp"android:layout_height="0dp"android:layout_weight="1"android:background="#FB7F02" /></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_marginLeft="3dp"android:background="@drawable/right_item_bg"android:gravity="center"android:orientation="vertical" ><ImageViewandroid:id="@+id/left_item_img"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_launcher" /><TextViewandroid:id="@+id/left_item_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#fff"android:text="这里可以放自定义的布局或内容" /></LinearLayout></LinearLayout>

同样的,右边布局的代码right_list_item.xml

<?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:baselineAligned="false"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="3dp"android:layout_weight="1"android:background="@drawable/left_item_bg"android:gravity="center"android:orientation="vertical" ><ImageViewandroid:id="@+id/right_item_img"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_launcher" /><TextViewandroid:id="@+id/right_item_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我是右边布局的内容"android:textColor="#fff" /></LinearLayout><LinearLayoutandroid:layout_width="20dp"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical" ><!-- 上下各画一根橙色的线条,线宽设置为2dp --><Viewandroid:layout_width="2dp"android:layout_height="0dp"android:layout_weight="1"android:background="#FB7F02" /><!-- 设置中间的节点大小为20x20 --><ImageViewandroid:layout_width="20dp"android:layout_height="20dp"android:src="@drawable/item_center_circle" /><Viewandroid:layout_width="2dp"android:layout_height="0dp"android:layout_weight="1"android:background="#FB7F02" /></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_marginLeft="3dp"android:layout_weight="1"android:gravity="center|left"android:orientation="vertical" ><TextViewandroid:id="@+id/right_tv_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="2016-06-27 14:45"android:textSize="14sp"android:textStyle="bold" /></LinearLayout></LinearLayout>

左右布局稍稍有些不一样,但是大同小异。好了下面开始讲代码了。核心主要在TimeLineAdapter,也就是这个ListView控件的适配器。注释我已经详细的写在代码中了,所以不做过多的解释。看代码

public class TimeLineAdapter extends BaseAdapter {/** 上下文环境 **/private Context mContext;/*** 实体类列表 建议最好用实体类,当然也可以用Map之类的来动态添加或生成, 我自己在这里建了一个实体类,配套后面的holder来用* **/private List<InfoBean> infoList;/** 对应要用到的实体类 **/private InfoBean infoBean;/** 布局渲染器 **/private LayoutInflater inflater;public TimeLineAdapter() {super();// TODO Auto-generated constructor stub}/*** 构造函数* * @param mContext*            上下文环境* @param infoList*            实体类列表*/public TimeLineAdapter(Context mContext, List<InfoBean> infoList) {super();this.mContext = mContext;this.infoList = infoList;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn infoList.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}/*** 注意这个方法最重要* */@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;// 如果convertView为空,则加载界面布局文件inflater = LayoutInflater.from(parent.getContext());// 如果为空,就重新加载布局文件if (null == convertView) {/** 由于我这里有两种不同的布局,而且是交叉呈现,所以做如下处理,将position对2求余,* 如果为0就加载左边布局,为1就加载右边布局*/if (position % 2 == 0) {// 加载左边布局convertView = inflater.inflate(R.layout.left_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.left_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.left_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.left_item_img);// 这里多了一个变量holder.isLeftOrRight = true;// 设置holder标签convertView.setTag(holder);} else {// 加载右边布局convertView = inflater.inflate(R.layout.right_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.right_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.right_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.right_item_img);// 这里多了一个变量holder.isLeftOrRight = false;// 设置holder标签convertView.setTag(holder);}} else {// 如果不为空,就直接从缓存中去取holder =  (ViewHolder)convertView.getTag();//本来直接这样取是没有问题的,但是会发现有重叠的bug// 所以接下来的处理是为了解决会出现的bug,如果有同学不明白的话,可以进下面的注释掉,然后运行一遍,就会发现问题了// 如何来解释这个呢?如果一屏幕有三个item,那么holder就将缓存三个item,到第四个的时候,// 就会将holder中原来缓存的第一个去覆盖第四个,这样就会出现,本来应该是右边出现的布局跑到了左边,还跟下面出现的布局重合的现象// 建议注释掉之后看效果,这样有点讲不明白if (0 == position%2 && !holder.isLeftOrRight) {// 加载左边布局convertView = inflater.inflate(R.layout.left_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.left_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.left_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.left_item_img);// 这里多了一个变量holder.isLeftOrRight = true;// 设置holder标签convertView.setTag(holder);}else if(1 == position%2 && holder.isLeftOrRight){// 加载右边布局convertView = inflater.inflate(R.layout.right_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.right_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.right_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.right_item_img);// 这里多了一个变量holder.isLeftOrRight = false;// 设置holder标签convertView.setTag(holder);}else{}      }// 在这里给holder中对应的控件填充内容for (int i = 0; i < infoList.size(); i++) {// 先遍历列表中的对象,一个个来填充infoBean = infoList.get(i);// 下面填充数据holder.mInfoDate.setText(infoBean.getInfoDate().toString());holder.mInfoContent.setText(infoBean.getInfoContent().toString());holder.mInfoIcon.setImageResource(infoBean.getInfoPicResourse());         }// 返回填充好了的convertViewreturn convertView;}/** 按照流行的写法,用holder来做缓存 **/public class ViewHolder {/** 时间 **/TextView mInfoDate;/** 内容 **/TextView mInfoContent;/** 新闻图标 **/ImageView mInfoIcon;/** 左布局还是由布局,为true表示加载左布局,为false表示加载右边布局 **/boolean isLeftOrRight;public ViewHolder() {super();}}}

对应的实体类infoBean

public class InfoBean {/** 时间 **/private String infoDate;/** 内容 **/private String infoContent;/** 图片 **/private int infoPicResourse;public InfoBean() {super();// TODO Auto-generated constructor stub}public String getInfoDate() {return infoDate;}public void setInfoDate(String infoDate) {this.infoDate = infoDate;}public String getInfoContent() {return infoContent;}public void setInfoContent(String infoContent) {this.infoContent = infoContent;}public int getInfoPicResourse() {return infoPicResourse;}public void setInfoPicResourse(int infoPicResourse) {this.infoPicResourse = infoPicResourse;}}

下面是MainActivity源码

public class MainActivity extends Activity implements OnItemClickListener{/**界面的ListView控件**/private ListView mTimeList ;/**时间轴适配器**/private TimeLineAdapter mAdapter ;/**对应的实体类的数据列表**/List<InfoBean> infoList = new ArrayList<InfoBean>();/**信息实体类**/InfoBean infoBean ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取控件,并为该控件绑定事件监听器mTimeList = (ListView) this.findViewById(R.id.timeLine);mTimeList.setOnItemClickListener(this);// 设置DIvider高度为0mTimeList.setDividerHeight(0);// 填充数据,这里也可以用Map来自己造数据,不需要另外在新建实体类for (int i = 0; i < 30 ; i++) {infoBean = new InfoBean();infoBean.setInfoDate("2016-06-28 18:30");infoBean.setInfoContent("我是内容详情");infoBean.setInfoPicResourse(R.drawable.ic_launcher);// 将实体添加到列表中infoList.add(infoBean);}       // 设置适配器mAdapter = new TimeLineAdapter(getApplicationContext(), infoList);       mTimeList.setAdapter(mAdapter);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// TODO Auto-generated method stubToast.makeText(getApplicationContext(), "你点击了" + position, 1000).show();}}

这里有异常的情况可以给大家展示一下,主要是这一句代码在处理异常,

         holder =  (ViewHolder)convertView.getTag();//本来直接这样取是没有问题的,但是会发现有重叠的bug// 所以接下来的处理是为了解决会出现的bug,如果有同学不明白的话,可以进下面的注释掉,然后运行一遍,就会发现问题了// 如何来解释这个呢?如果一屏幕有三个item,那么holder就将缓存三个item,到第四个的时候,// 就会将holder中原来缓存的第一个去覆盖第四个,这样就会出现,本来应该是右边出现的布局跑到了左边,还跟下面出现的布局重合的现象// 建议注释掉之后看效果,这样有点讲不明白if (0 == position%2 && !holder.isLeftOrRight) {// 加载左边布局convertView = inflater.inflate(R.layout.left_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.left_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.left_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.left_item_img);// 这里多了一个变量holder.isLeftOrRight = true;// 设置holder标签convertView.setTag(holder);}else if(1 == position%2 && holder.isLeftOrRight){// 加载右边布局convertView = inflater.inflate(R.layout.right_list_item, null);// 创建一个VIewHolder用以缓存holder = new ViewHolder();holder.mInfoDate = (TextView) convertView.findViewById(R.id.right_tv_time);holder.mInfoContent = (TextView) convertView.findViewById(R.id.right_item_content);holder.mInfoIcon = (ImageView) convertView.findViewById(R.id.right_item_img);// 这里多了一个变量holder.isLeftOrRight = false;// 设置holder标签convertView.setTag(holder);}else{}      

如果注释掉将会出现以下异常

好了,分享到此为止,鉴于我也是菜鸟一枚,大家可以相互学习和探讨,后面将给出去源码链接。

这种布局情况在手机上可能不多见,但是在比较大的屏幕上有可能用到,最近我自己在做的项目就用到了这个。

源码下载

竖直时间轴之左右交叉布局相关推荐

  1. 分享66个JS时间轴特效,总有一款适合您

    分享66个JS时间轴特效,总有一款适合您 66个JS时间轴特效下载链接:https://pan.baidu.com/s/1DD8EqIZjsmzpRB0pHkzUdg?pwd=pgw4  提取码:pg ...

  2. android时间轴左右交叉布局,快速简单的定制一个时间轴布局(LinearLayout)

    github: 先上图: 很多情况下,我们都会遇到需要类似于时间轴的一个布局,网上也有很多,但是很多情况下我们其实并不需要那么多库,毕竟64k限制就在那,不管我们用还是不用,它依然在那... 而且更多 ...

  3. html怎么做一条轴,html实现时间轴_纯css实现响应式竖着/垂直时间抽布局效果

    1.概述 html实现用时间点来展示事件发生点来代替用table展示一条条数据,能够给人清晰.一目了然能够看清事情发生的过程,UI页面也显示的那么清晰.如何用css+html做出时间轴展示事件点的?先 ...

  4. android 动画x轴旋转,Android Roate3dAnimation实现围绕y轴竖直方向或者绕x轴方向旋转的3d动画效果...

    概要: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Roate3dAnim ...

  5. [html] 写一个水平竖直居中的弹窗,带遮罩层的布局

    [html] 写一个水平竖直居中的弹窗,带遮罩层的布局 <div class="container"><div class="modal"&g ...

  6. highcharts特殊定制:x轴文字竖直显示(兼容各浏览器)

    做项目要用到highcharts画柱状图,可是x轴数据过多,如果文字从左至右显示显得拥挤不堪,于是想竖起显示,于是想到用xAxis的rotation属性,把文字旋转90度,可是这样文字显示虽然是竖直但 ...

  7. hype3 响应布局_使用Hype 3的基于时间轴的Web动画

    hype3 响应布局 Tumult的Hype 3是用于创建HTML5动画的OS X应用程序. 如果您曾经使用过Flash的标志性时间轴工具,那么Hype 3的界面似乎会非常熟悉. 在本教程中,我们将快 ...

  8. CSS盒子模型和水平、竖直方向的布局

    一.块元素.行内元素和行内块元素 行内元素特征: (1)设置宽高无效 (2)对margin仅设置左右方向有效,上下无效:padding设置上下左右都有效,即会撑大空间 (3)不会自动进行换行 块状元素 ...

  9. html css 水平时间轴,纯css+js水平时间轴

    自定义,并自动加载时间节点 当前时间节点居中,突出显示 时间动态无痕添加 效果图: 初始状态 时间左走到一定2016.1月后 html: + - 对应 JS 设置处理: var left = docu ...

最新文章

  1. title和alt属性
  2. 官宣!微软宣布桌面版 Edge将基于Chromium进行开发\n
  3. MATLAB可视化实战系列(二十四)-三维可视化如何利用圆锥图显示向量场?
  4. MAC地址表配置与绑定
  5. 力扣反转字符串中的元音字母
  6. linux vim 快速定位位置,vim快速移动定位的一些操作命令
  7. 离散数学之集合论【中】
  8. 【ES6(2015)】Generator
  9. python新手入门总结_写给已有编程经验的 Python 初学者的总结
  10. Python random模块sample、randint、shuffle、choice随机函数
  11. Verizon CEO证实公司正考虑出价收购雅虎
  12. VC2008中影响exe大小和速度的全部编译选项
  13. 极路由+锐捷校园网小白使用教程
  14. VS2019 安装 ReportViewer报表控件及设计器
  15. 微信扫码下载apk快速解决方案,中间页引导法
  16. [Python] 调用接口自动翻译单词,并存入文件
  17. outlook邮箱收件服务器密码,微软邮箱(hotmail+outlook):应用密码获取+STARTTLS加密...
  18. 华为云发布实时音视频行业加速器,为企业解决技术与商业双重难题
  19. word表格合并单元格后,光标居中
  20. 【转载】Android 面试总结

热门文章

  1. RV1108 EMMC 程序下载失败原因分析
  2. ol仿百度拖拽调整圆的大小的实现
  3. Android 自定义View实现炮弹射击小游戏
  4. 【python教程入门学习】利用Python写一场新年烟花秀
  5. 7-11 奥运排行榜(简洁AC+效率高)
  6. 【转】区块链:传统合同和智能合约
  7. hj-game策划案
  8. Windows组策略屏蔽U盘有妙法(图)
  9. 第一个Mybatis程序配置(代码)
  10. Java使用模板导出Word文档