Archive for 12 月, 2013
android开发日志-自适应宽度的AutoFitLinearLayout
最近需要实现一个如下图所示的列表
但是系统提供的GridView抑或是ListView均不能实现item自动排列
于是自己实现了一个
核心在于自己实现了adaper和view添加的事件,添加的时候决定是否生成一个新的line来容纳item
另外注意这个实现有一处优化的地方。
即若到第三行的时候,第三行放不下,会尝试从第一行开始计算,这样可以尽可能保证每行都是好看的效果
- /**
 - * Copyright 2013
 - * Created on : 13-11-27 , 上午11:53
 - * Author : haku
 - * Blog : http://haku.hk
 - */
 - public class AutoFitLinearLayout extends LinearLayout {
 - private DataSetObserver obv;
 - private BaseAdapter adapter;
 - private ArrayList<LinearLayout> lineViews = new ArrayList<LinearLayout>();
 - private AdapterView.OnItemClickListener itemClickListener;
 - private class ItemProxyClickListener implements OnClickListener {
 - int pos;
 - ItemProxyClickListener(int pos) {
 - this.pos = pos;
 - }
 - @Override
 - public void onClick(View v) {
 - itemClickListener.onItemClick(null, v, pos, 0);
 - }
 - }
 - public AutoFitLinearLayout(Context context, AttributeSet attrs) {
 - super(context, attrs);
 - this.setOrientation(LinearLayout.VERTICAL);
 - }
 - public AutoFitLinearLayout(Context context) {
 - super(context);
 - this.setOrientation(LinearLayout.VERTICAL);
 - }
 - /**
 - * 清空绑定view
 - */
 - public void reset() {
 - int total = lineViews.size();
 - for (int i = 0; i < total; i++) {
 - this.removeView(lineViews.get(i));
 - }
 - lineViews.clear();
 - }
 - /**
 - * @param adp
 - */
 - public void setAdapter(BaseAdapter adp) {
 - adapter = adp;
 - obv = new DataSetObserver() {
 - @Override
 - public void onChanged() {
 - super.onChanged();
 - reset();
 - int total = adapter.getCount();
 - for (int i = 0; i < total; i++) {
 - View v = adapter.getView(i, null, getLastLineHolder());
 - if (getItemClickListener() != null) {
 - v.setOnClickListener(new ItemProxyClickListener(i));
 - }
 - addToSuitableLayout(v);
 - }
 - }
 - };
 - adapter.registerDataSetObserver(this.obv);
 - }
 - public void addToSuitableLayout(View v) {
 - LinearLayout suitableLayout = getBestLineHolder(v);
 - suitableLayout.addView(v);
 - // 添加子view后重新计算宽度
 - suitableLayout.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
 - }
 - /**
 - * 添加一个水平的layout
 - *
 - * @return
 - */
 - public LinearLayout addNewLineHolder() {
 - LinearLayout v = new LinearLayout(this.getContext());
 - LayoutParams layoutParams = new LayoutParams(
 - ViewGroup.LayoutParams.MATCH_PARENT,
 - ViewGroup.LayoutParams.WRAP_CONTENT);
 - v.setOrientation(LinearLayout.HORIZONTAL);
 - v.setLayoutParams(layoutParams);
 - lineViews.add(v);
 - this.addView(v);
 - return v;
 - }
 - /**
 - * 自动计算宽度后反馈line holder
 - *
 - * @return
 - */
 - public LinearLayout getBestLineHolder(View v) {
 - // 计算子view的宽度和margin
 - v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
 - int viewWidth = v.getMeasuredWidth();
 - LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) v.getLayoutParams();
 - if (lineViews.isEmpty()) {
 - this.addNewLineHolder();
 - }
 - LinearLayout lHolder;
 - // 遍历所有存在的line,计算剩余宽度,如果适合就返回
 - for (int i = 0, size = lineViews.size(); i < size; i++) {
 - lHolder = lineViews.get(i);
 - int lineMaxWidth = lHolder.getMeasuredWidth();
 - if (lineMaxWidth + viewWidth + lp.leftMargin + lp.rightMargin < this.getMeasuredWidth()) {
 - return lHolder;
 - }
 - }
 - lHolder = this.addNewLineHolder();
 - return lHolder;
 - }
 - /**
 - * @return
 - */
 - public LinearLayout getLastLineHolder() {
 - if (lineViews.isEmpty()) {
 - this.addNewLineHolder();
 - }
 - // 得到最后一行,计算其剩余宽度
 - LinearLayout lHolder = lineViews.get(lineViews.size() – 1);
 - return lHolder;
 - }
 - public void setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) {
 - this.itemClickListener = itemClickListener;
 - }
 - public AdapterView.OnItemClickListener getItemClickListener() {
 - return itemClickListener;
 - }
 - }
 
