现在的位置: 首页 > 综合 > 正文

并排ListView——仿京东分类列表

2015年02月10日 ⁄ 综合 ⁄ 共 3809字 ⁄ 字号 评论关闭

无意间看到京东的分类列表做的非常炫, 是那种横排列表的形式,本来是想截图上来的,但是公司没找到数据线。。。。好吧,今天我们也来实现个这种效果。 这次我选择的ListView,但是ListView默认是横向铺满屏的,怎么做到并排呢? 重写!!!

虽然京东的没法截图了,但是我自己做的效果可以在模拟器上运行,先来看看效果吧,界面有点丑,没关系,对吧? 我们主要研究的是如何实现这种框架,而不是界面本身。

恩, 界面确实有点丑,算了,还是直接看实现过程吧。

上面说了,这次我们选重写ListView, 那么我们的需求是什么呢? 很简单,重写它默认横向铺满屏的特性,让它可以wrap_content。

public class MyListView extends ListView {
	public MyListView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}


	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int height = getMeasuredHeight();
		int width = 0;
		
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		if(widthMode == MeasureSpec.EXACTLY) {
			width = widthSize;
		}else {
			if(widthMode == MeasureSpec.AT_MOST) {
				final int childCount = getChildCount();
				for(int i=0;i<childCount;i++) {
					View view = getChildAt(i);
					measureChild(view, widthMeasureSpec, heightMeasureSpec);
					width = Math.max(width, view.getMeasuredWidth());
				}
			}
		}
		
		setMeasuredDimension(width, height);
	}
}

还是很简单的, 只重写了onMeasure()方法, 看看具体的逻辑吧。

13行,首先调用了super.onMeasure()方法,因为这里我们不考虑height,所以让ListView自己去算吧,我们只关心width/

14行,获取了ListView自己测量的结果,我们只需要height,因为width是我们自己需要计算的。

17~18行,不说了,获取父布局给推荐的mode和size。

接下来是一个if...else..., 在我们这个需求里,这个if...else...是多余的,但为了代码规范,还是加上了,有总比没有强吧。

if里,if的条件是widthMode == MeasureSpec.EXACTLY 即为精确值时, 这时候就不需要我们自己去计算了,直接赋值width为父布局给推荐的大小就ok。

看else里,这里又一个if,这个条件widthMode == MeasureSpec.AT_MOST 即当mode为尽量大时,也就是layout_width="wrap_content",好,这里需要我们自己做工作了。

23行,我们获取了所有的子item的个数。

接着24行一个for循环,获取所有的子view。

26行,通过measureChild(view, widthMeasureSpec, heightMeasureSpec);去测量一下该view的宽高。

27行,用width保存所有子view中宽度最大的那个的宽度。

最后的最后,32行,别忘了保存一下测量结果。


ok,重写的ListView搞定了,现在它就有了wrap_content的能力,赶紧来布局中布局它吧。

<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=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="3" >

        <org.loader.jdmemu.MyListView
            android:id="@+id/list1"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:background="@android:color/darker_gray" />
        <org.loader.jdmemu.MyListView
            android:id="@+id/list2"
            android:layout_width="0dip"
            android:layout_weight="2"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>

可以看到,这里是两个并排的ListView,占的宽度比为1:2。前期工作都做完了,去Activity中填充数据看看效果吧。

public class MainActivity extends Activity {
	private static final String[] mMenus = { "常用分类", "服饰内衣", "鞋靴", "手机",
			"家用电器", "数码", "电脑办公", "个护化妆", "图书" };

	private MyListView mListView1;
	private MyListView mListView2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mListView1 = (MyListView) findViewById(R.id.list1);
		mListView2 = (MyListView) findViewById(R.id.list2);
		
		mListView1.setAdapter(new ArrayAdapter<String>(this,
				R.layout.menu, mMenus));

		mListView1.setOnItemClickListener(new ItemClick());
	}
	
	private class ItemClick implements OnItemClickListener {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			mListView1.smoothScrollToPositionFromTop(position, 0);
			String[] items = new String[(position + 1) * 2];
			for(int i=0;i<items.length;i++) {
				items[i] = mMenus[position] + "中的数据:" + i;
			}
			mListView2.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, items));
		}
	}
}

恩,偷懒了,不过很好理解,就是为ListView1设置一个adapter,并通过ListView的itemClick动态改变ListView2的adapter。

重点看看

mListView1.smoothScrollToPositionFromTop(position, 0);

这句话的作用就是实现当我们点击该item时,让该ListView滑动,并到在该item到达顶部时停止,实现动画中那个自动滑动的ListView的效果。

如此简单,就可以达到文章刚开始的效果。

等等,突然想到,是不是可以把菜单做成侧滑的效果呢? 嘿嘿,应该还没有人这么干吧。 看来下篇文章可能就是“不一样的侧滑菜单了”。嘿嘿,今天下班回去研究研究。

抱歉!评论已关闭.