【Android开发—电商系列】(一):ListView,就这么美

导读

在本篇文章中,你将学到:

  • 如何实现广告位和列表的整体下拉刷新。
  • ListView的两层嵌套。
  • 如何让ListView中的一行显示多个Item。
  • -

先睹为快

项目的首页主要分为两部分:


  1. 上部的轮播广告位
  2. 下部的商品展示区,在每个商品类别(如,美食,服装,办公用品)下,最多展示6个商品。

效果图:

   【Android开发—电商系列】(一):ListView,就这么美_第1张图片

不同的分类:
   
  【Android开发—电商系列】(一):ListView,就这么美_第2张图片

布局思路

【Android开发—电商系列】(一):ListView,就这么美_第3张图片

描述:每个ListView都由HeadView、主体和FooterView组成。
整体:PullToRefreshListView
广告位:PullToRefreshListView的HeaderView
商品展示区:PullToRefreshListView的主体
每个商品大类(如美食类):PullToRefreshListView的一个Item
每个大类下的六个商品:ExpandedListView
每个商品:ExpandedListView的Item

实现

布局文件

首页布局:active_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="match_parent" android:layout_weight="1" tools:context=".MainActivity" >

    <!-- 顶部搜索框 -->

    <LinearLayout  android:id="@+id/main_top_layout" android:layout_width="match_parent" android:layout_height="45dp" android:layout_alignParentTop="true" android:background="@color/logoColor" android:focusableInTouchMode="true" android:gravity="center_horizontal" android:orientation="horizontal" >

        <ImageView  android:id="@+id/main_top_logo" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_gravity="center_vertical" android:layout_margin="5dp" android:src="@drawable/main_top_logo" />

        <EditText  android:id="@+id/main_search_edit" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="5dp" android:layout_weight="1" android:background="@drawable/bg_searchbox" android:focusable="false" android:focusableInTouchMode="true" android:hint="查询商品" android:padding="6dp" android:textColor="@color/darkgray" android:textSize="12sp" android:windowSoftInputMode="stateVisible|adjustPan" />

        <ImageView  android:id="@+id/index_search_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:paddingLeft="10dp" android:paddingRight="10dp" />
    </LinearLayout>


    <!-- 广告位和商品分类列表(整体都在一个下拉刷新的ListView当中) -->       
    <LinearLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="45dp">  

           <jczb.shoping.widget.PullToRefreshListView  android:id="@+id/product_floor_listview" style="@style/widget_listview" android:scrollbars="none" />      

     </LinearLayout>       


</RelativeLayout>

HeaderView布局:main_advertisement_header.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="wrap_content" android:orientation="vertical" >

    <RelativeLayout  android:layout_width="match_parent" android:layout_height="wrap_content" >
       <LinearLayout android:layout_width="match_parent" android:layout_height="136dp" android:background="#00FFFFFF">
            <!-- 广告位中可以左右滑动的控件 -->
        <android.support.v4.view.ViewPager android:id="@+id/adv_pager" android:layout_width="match_parent" android:layout_height="match_parent" >                   
        </android.support.v4.view.ViewPager> 
       </LinearLayout>

        <!-- 广告位中的小圆点 -->
        <LinearLayout  android:id="@+id/viewGroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="115dp" android:layout_marginRight="10dp" android:gravity="right" android:orientation="horizontal" >    
         </LinearLayout>  
    </RelativeLayout>


</LinearLayout>

商品大类Item布局:main_lv_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:orientation="vertical" android:background="#FFFFFF">

    <RelativeLayout  android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal" >
        <!-- 商品分类名称 -->
        <TextView  android:id="@+id/tv_category_name" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="美食" android:layout_alignParentLeft="true" android:layout_marginLeft="10dp" android:layout_marginTop="7dp" android:textSize="20dp" />
        <ImageView  android:id="@+id/iv_category_color" android:layout_width="7dp" android:layout_height="match_parent" android:background="#55D155"/>
        <!--更多箭头 -->
          <ImageView android:id="@+id/iv_product_more" android:layout_width="15dp" android:layout_height="15dp" android:layout_alignParentRight="true" android:layout_marginTop="14dp" android:layout_marginRight="5dp" android:layout_marginLeft="3dp" android:src="@drawable/tb_icon_actionbar_back1" />
        <!--更多文本 -->
        <TextView  android:id="@+id/tv_product_more" android:layout_height="wrap_content" android:layout_width="wrap_content" android:paddingRight="8dp" android:layout_toLeftOf="@id/iv_product_more" android:layout_marginTop="10dp" android:text="更多" android:textSize="16dp" />



    </RelativeLayout>

        <!-- 分割线 -->
        <View  android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#C0C0C0" />

    <!--商品大类 -->
    <jczb.shoping.adapter.ExpandedListView  android:id="@+id/elv_main_category" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#FFFFFFFF" android:listSelector="#00000000" >
    </jczb.shoping.adapter.ExpandedListView>
    <!-- 分割线 -->
        <View  android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#C0C0C0" />
    <!-- 分割线 -->
        <View  android:layout_width="match_parent" android:layout_height="8dp" android:background="#F6F9FE" />


</LinearLayout>

每个商品的Item布局:main_lv_item_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:orientation="horizontal" >

<!--每行展示 2个商品-->    
<LinearLayout  android:layout_width="fill_parent" android:layout_height="250dp" android:layout_marginLeft="0dp" android:layout_marginRight="0dp" android:layout_marginTop="0dp" android:layout_marginBottom="0dp" android:orientation="horizontal" >

     <RelativeLayout  android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" >
            <ImageView  android:id="@+id/iv_main_product_1" android:layout_width="match_parent" android:layout_height="170dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginBottom="10dp" android:background="#FFFFFF" android:scaleType="fitXY" />
            <TextView  android:id="@+id/tv_main_productName_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/iv_main_product_1" android:layout_alignLeft="@id/iv_main_product_1" android:layout_marginBottom="5dp" android:layout_marginLeft="5dp" android:textSize="13dp" android:lines="2" android:ellipsize="end" />

            <TextView  android:id="@+id/tv_main_productPrice_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_main_productName_1" android:layout_marginLeft="5dp" android:textColor="#E2572D" android:textSize="14dp"/>


        </RelativeLayout>
        <RelativeLayout  android:layout_width="2dp" android:layout_height="fill_parent" android:background="#FFFFFF" >




        </RelativeLayout>
        <RelativeLayout  android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" >

            <ImageView  android:id="@+id/iv_main_product_2" android:layout_width="match_parent" android:layout_height="170dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginBottom="10dp" android:background="#FFFFFF" android:scaleType="fitXY" />
            <TextView  android:id="@+id/tv_main_productName_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/iv_main_product_2" android:layout_marginLeft="5dp" android:textSize="13dp" android:lines="2" android:ellipsize="end" android:layout_marginBottom="5dp" />

            <TextView  android:id="@+id/tv_main_productPrice_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_main_productName_2" android:layout_marginLeft="5dp" android:textColor="#E2572D" android:textSize="14dp"/>
        </RelativeLayout>



    </LinearLayout>



</LinearLayout>

ListView

  • PullToRefreshListView(此处省略)
  • ExpandedListView
package jczb.shoping.adapter;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.ListView;
/** * 用于ListView的嵌套,这个ListView当中可以嵌套ListView * @author xuchenyang * 2015年11月9日21:43:01 */
public class ExpandedListView extends ListView{

    public ExpandedListView(Context context) {
        super(context);
        setBackgroundColor(Color.argb(100, 0, 55, 55));
    }



    public ExpandedListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }


    public ExpandedListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);

        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

Adapter

  • PullToRefreshListView的Adapter
        product_floor_listview.setAdapter(new BaseAdapter() {       
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {             
                View inflate = getLayoutInflater().inflate(R.layout.main_lv_item, null);

                /*设置商品分类名称*/
                //获得显示商品分类的控件
                TextView tvCategoryName=(TextView)inflate.findViewById(R.id.tv_category_name);
                //从数据集合中获得分类名称 
                String strCategoryName=lstHomePage.get(position).getName();
                //设置控件文本 
                tvCategoryName.setText(strCategoryName);

                /*设置商品分类名称的颜色*/
                ImageView ivCategoryColor=(ImageView)inflate.findViewById(R.id.iv_category_color);
                //黄,绿,红,蓝
                String[] colorValues={"#FFFF77","#55D155","#DB3031","#6278D9"};
                int colorIndex=position % 4;
                int colorValue=Color.parseColor(colorValues[colorIndex]);
                ivCategoryColor.setBackgroundColor(colorValue);

                /*设置每个分类下的商品*/
                List<Product> lstProduct=lstHomePage.get(position).getProduct();                
                ListView listView = (ListView) inflate.findViewById(R.id.elv_main_category);
                productAdapter=new MainListViewAdapter(MainActivity.this,lstProduct);
                listView.setAdapter(productAdapter);

                return inflate;
            }

            @Override
            public long getItemId(int position) {
                return position;
            }

            @Override
            public Object getItem(int position) {
                return lstHomePage.get(position);
            }
            /** * 显示的商品类别数 */
            @Override
            public int getCount() {             
                return lstHomePage.size();
            }
        });


        /*添加下拉刷新事件*/
        product_floor_listview.setOnRefreshListener(new OnRefreshListener(){

            @Override
            public void onRefresh() {
                // Do work to refresh the list here.
                new GetDataTask().execute();

            }

        }); 
    } 
  • MyListViewAdapter
package jczb.shoping.adapter;

import java.util.List;

import jczb.shoping.common.UIHelper;
import jczb.shoping.model.Product;
import jczb.shoping.model.URLs;
import jczb.shoping.ui.ProductsInfoActivity;
import jczb.shoping.ui.R;
import net.tsz.afinal.FinalBitmap;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/** * 首页每个分类下商品展示的ListView的Adapter * @author xuchenyang * 2015年11月9日20:11:10 */
public class MainListViewAdapter extends BaseAdapter {
    //某个商品分类下商品集合
    private List<Product> list;
    private Context context;
    private FinalBitmap fb;

    public MainListViewAdapter(Context context, List<Product> list) {
        this.context = context;
        fb = FinalBitmap.create(context);
        this.list = list;
    }

    /** * 获得记录的行数 */
    @Override
    public int getCount() {

        // 按每行2个显示,算出共显示的行数
        if (list.size() % 2 == 0) {
            return list.size() / 2;
        }

        return list.size() / 2 + 1;
    }

    /** * 获得每个条目项 */
    @Override
    public Object getItem(int position) {       
        return list.get(position);
    }

    /** * 获得每个条目的Id */
    @Override
    public long getItemId(int position) {       
        return position;
    }

    /** * 获得每个条目的视图 */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder viewHolder = null;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = View.inflate(context, R.layout.main_lv_item_item, null);
            //商品的图片
            viewHolder.iv_product1 = (ImageView) convertView
                    .findViewById(R.id.iv_main_product_1);
            viewHolder.iv_product2 = (ImageView) convertView
                    .findViewById(R.id.iv_main_product_2);
            //商品名称
            viewHolder.tv_name1=(TextView)convertView.findViewById(R.id.tv_main_productName_1);
            viewHolder.tv_name2=(TextView)convertView.findViewById(R.id.tv_main_productName_2);

            //商品价格
            viewHolder.tv_price1=(TextView)convertView.findViewById(R.id.tv_main_productPrice_1);
            viewHolder.tv_price2=(TextView)convertView.findViewById(R.id.tv_main_productPrice_2);

            convertView.setTag(viewHolder);

        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        int position1 = position *2;
        int position2 = position * 2 + 1;

        Product product1=list.get(position1);

        /********每行第一个产品的设置********/
        //显示产品图片
        String pic1 = URLs.imageUrlPrefix+product1.getPro_img();
        fb.display(viewHolder.iv_product1, pic1);
        //假数据
        //viewHolder.iv_product1.setImageResource(R.drawable.clothing_04);
        //显示产品名称
        viewHolder.tv_name1.setText(product1.getPro_name());
        //显示产品价格
        viewHolder.tv_price1.setText("¥"+product1.getPro_price());

        //把该产品的位置设为图片的tag值,为的是点击图片时能获得它的位置
        //viewHolder.iv_product1.setTag(position1);
        //把商品的Id保存到Tag中
        viewHolder.iv_product1.setTag(product1.getUid());
        /***********每行第二个产品的设置*******/
        if (position2 < list.size()) {
            Product product2=list.get(position2);
            String pic2 =URLs.imageUrlPrefix+product2.getPro_img();
            fb.display(viewHolder.iv_product2, pic2);
            //viewHolder.iv_product2.setImageResource(R.drawable.clothing_0108);
            //显示产品名称
            viewHolder.tv_name2.setText(product2.getPro_name());
            //显示产品价格
            viewHolder.tv_price2.setText("¥"+product2.getPro_price());
            //viewHolder.iv_product2.setTag(position2);
            viewHolder.iv_product2.setTag(product2.getUid());

        } else {
            //viewHolder.iv_product2.setVisibility(View.GONE);
        }


        viewHolder.iv_product1.setOnClickListener(new View.OnClickListener() { 

            @Override 
            public void onClick(View v) { 

                UIHelper.ToastMessage(context, v.getTag().toString());
                //获得产品uid
                int uid=Integer.parseInt(v.getTag().toString());
                StartProductInfoActivity(uid);
            } 
        }); 
        viewHolder.iv_product2.setOnClickListener(new View.OnClickListener() { 

            @Override 
            public void onClick(View v) { 
                if(v.getTag()!=null){
                    UIHelper.ToastMessage(context, v.getTag().toString());
                    //获得产品uid
                    int uid=Integer.parseInt(v.getTag().toString());
                    StartProductInfoActivity(uid);
                }


            } 
        }); 

        return convertView;
    }

    /** * 每个条目项的视图集合 * @author xuchenyang * */
    class ViewHolder {

        private ImageView iv_product1, iv_product2;
        private TextView tv_name1,tv_name2,tv_price1,tv_price2;

    }

    /** * 启动商品详情页 * @param uid 商品id */
    public void StartProductInfoActivity(int uid){
        Intent intent=new Intent();
        intent.putExtra("uid", uid);
        intent.setClass(context, ProductsInfoActivity.class);
        context.startActivity(intent);
    }
}

总结

  • 实现广告位和列表的整体下拉刷新:
    将广告位作为ListView的HeaderView。
  • ListView的两层嵌套:
    嵌套进去的ListView要重新实现OnMeasure方法,否则会报错。
  • 如何让ListView中的一行显示多个Item:
    在Adapter的getCount方法中进行处理。

  基本的ListView我想大家都会实现,但是在这个用户体验度要求很高的Android世界里,怎么能不玩出一点花样呢?ListView,原来可以展现出这么好看的界面,太棒了!有没有豁然开朗的感觉?所以尽情想象吧,我已经陶醉了……

附:下载源码

你可能感兴趣的:(android,ListView,嵌套,下拉刷新,一行多个显示)