利用ListView实现类似物流详情的进度显示

背景:点击产品单号列表中的进度查看按钮,跳转至进度页面,显示该产品单号的进度。

真实物流的信息当然是动态生成的,此处产品单号的数据是顺序且固定的,仿照的只是物流详情的UI。

实现效果图:

一、UI实现

页面布局文件:

<?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:orientation="vertical" >
    <include layout="@layout/titile_1"></include>
    
    <LinearLayout 
        android:orientation="horizontal"
        android:paddingTop="15dp"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:paddingLeft="20dp"
        android:background="@color/white">
        <TextView 
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:id="@+id/process_code"
            android:textSize="18dp"
            android:paddingLeft="5dp"
            android:textStyle="bold|italic"/>
        <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/emblem"
            android:id="@+id/process_img"
            android:scaleType="fitXY"
            android:listSelector="@android:color/transparent"
            android:layout_marginRight="30dp"
            />
    </LinearLayout>
    
    <ListView
        android:layout_marginTop="8dp"
        android:paddingBottom="10dp"
        android:id="@+id/process_list"
        android:background="@color/white"
        android:clickable="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:divider="#00000000">    
    </ListView>

android:divider="#00000000"将ListView的分割线设为透明,并且设置无法获取焦点和无法点击

ListView的item布局:

<?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:orientation="horizontal"
    android:gravity="center_horizontal" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_weight="9"
        android:gravity="center_horizontal">

        <View
            android:id="@+id/item_driver1"
            android:layout_width="0.5dp"
            android:layout_height="20dp"
            android:background="@color/black"
            android:layout_marginLeft="7.3dp"/>

        <ImageView
            android:id="@+id/item_node"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/item_driver1"
            android:src="@drawable/node_pass"
            android:scaleType="fitXY"/>

        <View
            android:id="@+id/item_driver2"
            android:layout_width="0.5dp"
            android:layout_height="30dp"
            android:layout_below="@id/item_node"
            android:background="@color/black"
            android:layout_marginLeft="7.3dp"/>
    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_weight="2"
        android:background="@color/white"
        android:orientation="horizontal" 
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
        android:paddingLeft="12dp"
        android:layout_marginRight="12dp">

        <TextView
            android:id="@+id/pro_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/pro_status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

左边图片部分,由两条View和一个ImageView实现,ImageView的两个图片:

ImageView图片默认是灰色,在代码中将最新的状态设置为绿色图片

二、数据实现

Java代码:

package com.example.cwapp.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.example.cwapp.R;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class ProcessActivity extends Activity {
    private ListView list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.process);
        Bundle bundle = getIntent().getExtras();
        String process = bundle.getString("pro");
        
        list = (ListView) findViewById(R.id.process_list);
       
        ArrayList<HashMap<String, Object>> all = new ArrayList<HashMap<String, Object>>();
        List<HashMap<String, Object>> array = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> map0 = new HashMap<String, Object>();
        map0.put("pro_status", "您的订单开始处理");
        HashMap<String, Object> map1 = new HashMap<String, Object>();
        map1.put("pro_status", "您的订单待配货");
        HashMap<String, Object> map2 = new HashMap<String, Object>();
        map2.put("pro_status", "您的包裹已出库");
        HashMap<String, Object> map3 = new HashMap<String, Object>();
        map3.put("pro_status", "包裹正待等待揽收");
        HashMap<String, Object> map4 = new HashMap<String, Object>();
        map4.put("pro_status", "xx快递已揽件");
        all.add(map4);
        all.add(map3);
        all.add(map2);
        all.add(map1);
        all.add(map0);

        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("您的订单开始处理", 0);
        map.put("您的订单待配货", 1);
        map.put("您的包裹已出库", 2);
        map.put("包裹正待等待揽收", 3);
        map.put("xx快递已揽件", 4);
        switch (map.get(process)) {
        case 0:
            array = all.subList(4, 5);
            break;
        case 1:
            array = all.subList(3, 5);
            break;
        case 2:
            array = all.subList(2, 5);

            break;
        case 3:
            array = all.subList(1, 5);

            break;
        case 4:
            array = all.subList(0, 5);
            break;
        }
        mySimpleAdapter adapter = new mySimpleAdapter(ProcessActivity.this, array,
                R.layout.process_item, new String[] { "pro_status" },
                new int[] { R.id.pro_status });
        list.setAdapter(adapter);
        list.setOnTouchListener(new View.OnTouchListener() {
            
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

    }

    class mySimpleAdapter extends SimpleAdapter {
        private ImageView node;
        private View view;
        private TextView status;
        @Override
        public int getCount() {
            return super.getCount();
        }

        public mySimpleAdapter(Context context,
                List<? extends Map<String, ?>> data, int resource,
                String[] from, int[] to) {
            super(context, data, resource, from, to);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("getView");
            convertView = getLayoutInflater()
                    .inflate(R.layout.process_item, null);
            
            if(position == 0){
                node = (ImageView)convertView.findViewById(R.id.item_node);
                node.setImageResource(R.drawable.node_now);
                view = convertView.findViewById(R.id.item_driver1);
                view.setVisibility(View.INVISIBLE);
                status = (TextView)convertView.findViewById(R.id.pro_status);
                status.setTextColor(Color.parseColor("#4FBA6F"));
            }
            return super.getView(position, convertView, parent);
        }
    }
}

用ArrayList变量all将一个产品单号的全部状态按顺序存储起来,String变量process是传来的产品单号最新的进度状态,由于状态顺序是固定的,每个状态所处的位置已知,此时只许根据process的值来分割all,得到的的子集作为适配器的数据源。(注意为实现从上往下时间降序的效果,all按时间降序存储,分割子集时则需要从尾部进行分割)

分割技巧:如果使用 if 语句依次判断process的值来进行分割,代码冗余。这里用Map和switch-case将字符串转换成数值(解决switch case无法匹配字符串的问题):事先用HashMap<String,Integer> map把字符串作为key,为其设置一个数值value存储;在对str字符串进行匹配时,根据map.get(str)获得其对应的数值,最后通过switch-case判断数值转到对应项。此处利用上述技巧:为每个状态设置一个数值,map.get(process)获得process的对用数值,switch case匹配跳转实现分割。

设置ListView监听器重写onTouch返回true,去除ListView的点击效果。参考View的事件分发机制。

list.setOnTouchListener(new View.OnTouchListener() {
            
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

自定义SimpleAdapter,重写getView绘图。把最新状态的文字变为绿色,其所在item的ImageView图片变为绿色图片,保留ImageView下面的View,隐藏上面的View,需要注意的是array把正常进度顺序反向存储,最底层是最新状态,所以getView中的判断条件是position == 0。

 
 
 
 

 

转载于:https://www.cnblogs.com/mariana/p/7112485.html

一款简单的物流状态进度展示自定义View,仅供参考学习效果图使用方法布局文件<ExpressView         android:id="@ id/expressview"         android:layout_width="match_parent"         android:layout_height="match_parent"         express:circleToTextMargin="12dp"         express:expressCircleOuterRadius="8dp"         express:expressCircleRadius="6dp"         express:expressTextMargin="12dp"         express:expressTextSize="14sp"         express:expressTextVecPadding="5dp"         express:expressTimeTextSize="10sp"         express:firstExpressCircleMarginLeft="16dp"         express:firstExpressCircleMarginTop="16dp"         express:isTimeButtonVisible="true" />控件属性介绍firstExpressCircleMarginLeft 第一个物流状态点距离父控件坐边的间距 firstExpressCircleMarginTop 第一个物流状态点距离父控件上边的间距 expressCircleRadius 物流状态点内圈半径 expressCircleOuterRadius 物流状态点外圈半径 circleToTextMargin 物流状态提示圈到文字背景的距离 expressTextMargin 文字距离背景边距 expressTextVecPadding 每个物流信息竖直方向的间距 expressTextSize 文字大小 expressTimeTextSize 时间文字大小 isTimeButtonVisible 是否显示时间和文字按钮客户端        //数据源         final List<ExpressMessageBean> list = new ArrayList<>();        ExpressMessageBean bean = new ExpressMessageBean();         bean.setFlowState(1);         bean.setFlowStateBtRight("购买流程");         bean.setCreateTime(1487259871184l);         bean.setCreateTimeFormat(TimeUtils.millis2String(1487259871184l));         bean.setOpContent("您已付款0.1200元,购买 地下城与勇士/广东区/广东1区帐号,请联系卖家卡罗特将密保手机绑定您的手机号 189****2298");         list.add(bean);         bean = new ExpressMessageBean();         bean.setFlowState(4);         bean.setFlowStateBtLeft("同意退款"); //设置左右按钮文字         bean.setFlowStateBtRight("拒绝退款");         bean.setCreateTime(1487259991260l);         bean.setCreateTimeFormat(TimeUtils.millis2String(1487259991260l));         bean.setOpContent("天空套 0.1200 1个-申请退款");         list.add(bean);         bean = new ExpressMessageBean();         bean.setFlowState(5);         bean.setCreateTime(1487259871184l);         bean.setCreateTimeFormat(TimeUtils.millis2String(1487259871184l));         bean.setOpContent("您已付款0.1200元,购买 地下城与勇士/广东区/广东1区帐号,请联系卖家卡罗特将密保手机绑定您的手机号 189****2298");         list.add(bean);         bean = new ExpressMessageBean();         bean.setFlowState(1);         bean.setFlowStateBtRight("购买流程"); //设置右按钮文字         bean.setCreateTime(1487259991260l);         bean.setCreateTimeFormat(TimeUtils.millis2String(1487259991260l));         bean.setOpContent("天空套 0.1200 1个-申请退款");         list.add(bean);        //数据源适配         ExpressViewAdapter adapter = new ExpressViewAdapter<ExpressMessageBean>(list) {            @Override             public ExpressViewData bindData(ExpressView expressView, int position, ExpressMessageBean expressMessageBean) {                ExpressViewData data = new ExpressViewData();                 data.setContent(expressMessageBean.getOpContent());                 data.setTime(expressMessageBean.getCreateTimeFormat());                 data.setLeftBtnText(expressMessageBean.getFlowStateBtLeft());                 data.setRightBtnText(expressMessageBean.getFlowStateBtRight());                return data;             }         };         expressView.setAdapter(adapter);         adapter.notifyDataChanged();        //处理点击事件         expressView.setOnExpressItemButtonClickListener(new ExpressView.OnExpressItemButtonClickListener() {            @Override             public void onExpressItemButtonClick(int position, int status) {                switch (list.get(position).getFlowState()){                    case 1:                         if(status == 1){ //购买流程                             ToastUtil.ToastBottow(TestActivity.this, list.get(position).getFlowStateBtRight());                         }                        break;                    case 4:                         if(status == 0) { //同意退款                             ToastUtil.ToastBottow(TestActivity.this, list.get(position).getFlowStateBtLeft());                         } else if(status == 1){ //拒绝退款                             ToastUtil.ToastBottow(TestActivity.this, list.get(position).getFlowStateBtRight());                         }                        break;                    default:                         break;                 }             }         });待完善1、处理滑动冲突2、处理滑动到顶部和到底部停止滑动的逻辑3、实现弹性滑动的效果博客文章介绍http://www.jianshu.com/p/2d87f62d5d27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值