androud ListView 仿 IPhone UITable Title效果(有Title数据不更改缺陷。&待续)


android ListView的分组实现方式参照了以下博客链接的实现方式在此基础上修改。

http://wang-peng1.iteye.com/blog/578411


类似实现方法可参照源码----通讯录-PinnedHeaderListView

以下实现方法缺点:

1、Title透明向上时上一分组的最后一个Cell会被看见。

2、SectionedAdapter的实现方式对于ListView中的Cell重用机制处理的不是很好。

3、Title的实现方式是以Bitmap形式绘制,N多个大Title载入后不能保证不内存溢出。


使用AbsoluteLayout+LIstView实现可能更简便。


SectionedAdapter继承自BaseAdapter 实现了多个Adapted的分组。

以上博客地址在滑动后出现分组Title和Cell的布局加载错误。在此基础上做了以下修改。

abstract public class SectionedAdapter extends BaseAdapter {
	abstract protected View getHeaderView(String caption,int index,View convertView,ViewGroup parent);
	
	private List<Section> sections=new ArrayList<Section>();
	private static int TYPE_SECTION_HEADER=0;
	private Context mContext;
	public SectionedAdapter(Context mContext) {	
		super();
		this.mContext = mContext;
	}

	public void addSection(String caption, Adapter adapter, int res) {
		sections.add(new Section(caption, adapter, res));
	}

	@Override
	public Object getItem(int position) {
		for (Section section : this.sections) {
			if (position==0) {
				return(section);
			}
			
			int size=section.adapter.getCount()+1;

			if (position<size) {
				return(section.adapter.getItem(position-1));
			}

			position-=size;
		}
		
		return(null);
	}

	@Override
	public int getCount() {
		int total=0;
		
		for (Section section : this.sections) {
			total+=section.adapter.getCount()+1; // add one for header
		}
		
		return(total);
	}

	@Override
	public int getViewTypeCount() {
		int total=1;	// one for the header, plus those from sections
		
		for (Section section : this.sections) {
			total+=section.adapter.getViewTypeCount();
		}
		
		return(total);
	}

	@Override
	public int getItemViewType(int position) {
		int typeOffset=TYPE_SECTION_HEADER+1;	// start counting from here
		
		for (Section section : this.sections) {
			if (position==0) {
				return(TYPE_SECTION_HEADER);
			}
			
			int size=section.adapter.getCount()+1;

			if (position<size) {
				return(typeOffset+section.adapter.getItemViewType(position-1));
			}

			position-=size;
			typeOffset+=section.adapter.getViewTypeCount();
		}
		
		return(-1);
	}

	public boolean areAllItemsSelectable() {
		return(false);
	}

	@Override
	public boolean isEnabled(int position) {
		return(getItemViewType(position)!=TYPE_SECTION_HEADER);
	}

	@Override
	public View getView(int position, View convertView,
											ViewGroup parent) {
		int sectionIndex=0;
		
		for (Section section : this.sections) {
			if (position==0) {
				return(getHeaderView(section.caption, sectionIndex,convertView, parent));
			}

			int size=section.adapter.getCount()+1;
			if (position<size) {
				if(convertView!=null && convertView.getTag().equals(section.res))
					convertView = section.adapter.getView(position-1,	convertView,parent);
				else {
					convertView = LayoutInflater.from(mContext).inflate(section.res, null);
					convertView = section.adapter.getView(position-1,	convertView,parent);
					convertView.setTag(section.res);
				}
				return(convertView);
			}

			position-=size;
			sectionIndex++;
		}
		
		return(null);
	}

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

	class Section {
		String caption;
		Adapter adapter;
		int res;
		Section(String caption, Adapter adapter,int res) {
			this.caption=caption;
			this.adapter=adapter;
			this.res = res;
		}
	}
}


StartAct 程序入口在其中实现了SectionedAdapter对Title的加载

public class StartAct extends Activity {
    /** Called when the activity is first created. */
	SectionedAdapter sectionAdapter;
	UITableView tableView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//      数据导入
        sectionAdapter = new SectionedAdapter(this) {
			
			@Override
			protected View getHeaderView(String caption, int index, View convertView,
					ViewGroup parent) {
				// TODO Auto-generated method stub
				TextView result=(TextView)convertView;
				if (result==null || convertView.getTag()!=null && !convertView.getTag().equals("title")) {
					
					result=(TextView)getLayoutInflater().inflate(R.layout.header, null);
					result.setTag("title");
				}
				result.setText(caption);
				return result;
			}
		};
//		
		tableView = new UITableView(this);
		this.setContentView(tableView);
		tableView.setAdapter(sectionAdapter);
		for(int i =0;i<10;i++) {
			ArrayAdapter<String> a = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new String[] {"1","1","1","1","1"});
			sectionAdapter.addSection("Title"+i, a,android.R.layout.simple_list_item_1);
		}
    }
    
}

UITableView 继承自ListView。实现OnScrollListener

在父类的dispatchDraw方法中重绘Title

public class UITableView extends ListView implements OnScrollListener {
	private static final int MAX_ALPHA = 255;
	private TreeMap<String, Bitmap> titlemap;
	private List<String> keylist;
	private int Section;
	private View mHeadView;
	private Paint mPaint;
	int titledy;
	public UITableView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		Section = 0;
		titlemap = new TreeMap<String, Bitmap>();
		keylist = new ArrayList<String>();
		mPaint = new Paint();
		this.setVerticalFadingEdgeEnabled(false);
		this.setOnScrollListener(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.widget.ListView#dispatchDraw(android.graphics.Canvas)
	 */

	@Override
	protected void dispatchDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.dispatchDraw(canvas);
		if(mHeadView == null) 
			return;
		canvas.save();
		int childid = this.getPositionForView(this.getChildAt(0));
		String titlekey = "";
		String key = "" + Section;
		titledy = 0;
		mPaint.setAlpha(MAX_ALPHA);
		Log.d("TAG", "childid:" + childid + "----Section:" + Section+"-----index:"+keylist.indexOf(key));
		if (childid < Section) {
			if (keylist.contains(key) && keylist.indexOf(key) > 0) {
				titlekey = keylist.get(keylist.indexOf(key)-1);
			} else {
				titlekey = keylist.get(0);
			}
//			标签移动计算
			if(mHeadView.getTop()<=mHeadView.getHeight()) {
				titledy-=(mHeadView.getHeight()-mHeadView.getTop());
				int alpha = (int) (MAX_ALPHA*(mHeadView.getTop()*1.0f/mHeadView.getHeight()));
				mPaint.setAlpha(alpha);
			}
		}else if(childid == Section) {
			titlekey = keylist.get(keylist.indexOf(key));
			titledy = 0;
		}else if(childid >Section && keylist.indexOf(key)== keylist.size()-1){
			titlekey = keylist.get(keylist.size()-1);
			titledy = 0;
		}
		if (titlemap.get(titlekey) != null)
			canvas.drawBitmap(titlemap.get(titlekey), 0, titledy, mPaint);
		canvas.restore();
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// TODO Auto-generated method stub
		for (int i = 0; i < visibleItemCount; i++) {
			Object obj = this.getAdapter().getItem(firstVisibleItem + i);
			if (obj.getClass() == SectionedAdapter.Section.class) {
				if (titlemap.get("" + (firstVisibleItem + i)) == null) {
					this.getChildAt(i).setDrawingCacheEnabled(true);
					Bitmap bmp = Bitmap.createBitmap(this.getChildAt(i)
							.getDrawingCache());
					if (!bmp.isRecycled()) {
						titlemap.put("" + (firstVisibleItem + i), bmp);
						if (!keylist.contains("" + (firstVisibleItem + i))) {
							keylist.add("" + (firstVisibleItem + i));
						}
					}
					this.getChildAt(i).setDrawingCacheEnabled(false);
				}
				Section = firstVisibleItem + i;
				mHeadView = this.getChildAt(i);
				break;
			}
		}
	}
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值