一、ListView圓角:重寫ListView的onInterceptTouchEvent方法,通過(guò)pointToPosition(x,y)方法判斷當(dāng)前點(diǎn)擊位置所對(duì)應(yīng)的項(xiàng),有三種情況:分別是第一項(xiàng)、最后一項(xiàng)、中間項(xiàng);其實(shí)第一種情況又分為兩種情況:列表總共只有一項(xiàng)和列表不止一項(xiàng);參照下邊的代碼即可理解;
復(fù)制代碼
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
int x = (int) ev.getX();
int y = (int) ev.getY();
int itemnum = pointToPosition(x, y);
if (itemnum == AdapterView.INVALID_POSITION)
break;
else{
if(itemnum==0){ // 選擇項(xiàng)為1
if(itemnum==(getAdapter().getCount()-1)){// 列表只有一項(xiàng)
setSelector(R.drawable.app_list_corner_round);
}else{ // 列表不止一項(xiàng)
setSelector(R.drawable.app_list_corner_round_top);
}
}else if(itemnum==(getAdapter().getCount()-1)) // 選擇項(xiàng)為最后一項(xiàng)
setSelector(R.drawable.app_list_corner_round_bottom);
else{
setSelector(R.drawable.app_list_corner_shape);
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
復(fù)制代碼
二、選中項(xiàng)高亮顯示,實(shí)現(xiàn)ListView選中項(xiàng)高亮顯示有兩種方法;
1、查看ListView的方法setSelection(int index),看樣子好像是,但實(shí)際試了之后以現(xiàn)不行,既然不行,那就用一個(gè)比較笨的方法:自定義adapter,在adapter的getView方法里面設(shè)置背景;然后在ListView的onItemClick回調(diào)中向adapter傳入點(diǎn)擊的項(xiàng),即可設(shè)置選中項(xiàng)高亮狀態(tài);
復(fù)制代碼
public void setSelectedposition(int selectedposition) {
this.selectedposition = selectedposition;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.item, null);
if (selectedposition == position) {
v.setBackgroundColor(Color.parseColor("#36adcf"));
} else {
v.setBackgroundColor(Color.TRANSPARENT);
}
return v;
}
復(fù)制代碼
2、有沒(méi)有更簡(jiǎn)單的方法?第一種方法看著覺(jué)得有點(diǎn)怪怪的,有點(diǎn)歪門邪道的感覺(jué);另一種的方法是通過(guò)selector方法實(shí)現(xiàn);定義一個(gè)drawable文件,里面包含一個(gè)選擇狀態(tài):state_activated,然后將這個(gè)drawable指定為L(zhǎng)istView的item的背景;關(guān)于這個(gè)狀態(tài)具體含意不再多說(shuō),參見(jiàn)官方api;
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas./apk/res/android">
<item android:drawable="@drawable/adcf" android:state_activated="true"></item>
<item android:drawable="@android:color/transparent"/>
</selector>
下面是在代碼中的實(shí)現(xiàn)(部分代碼):
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
getListView().setItemChecked(position, true);
}
注:上面的方法是ListActivity的方法,此方法對(duì)應(yīng)OnItemClickListener接口中的方法;
三、ListView列表項(xiàng)延遲加載
我們都知道當(dāng)ListView上面滾動(dòng)時(shí),會(huì)執(zhí)行adapter的getView方法,但問(wèn)題出來(lái)了,有時(shí)候?yàn)榱斯?jié)約資源及解決效率問(wèn)題,并不需要滾動(dòng)到某一項(xiàng)就開始加載數(shù)據(jù),而是希望滾動(dòng)停止,或者說(shuō)滾動(dòng)速度低于某一個(gè)值時(shí)才獲取數(shù)據(jù),下面討論的就是這種情況下的處理:
1、為L(zhǎng)istView添加OnScrollListener滾動(dòng)監(jiān)聽器,此監(jiān)聽器可以獲取當(dāng)前滾動(dòng)狀態(tài)及可視條目;
復(fù)制代碼
public int first = 0; // 第一條可視項(xiàng)目
public int visi = 0; // 可視條目總數(shù)
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
first = firstVisibleItem;
visi = visibleItemCount;
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE: // 滾動(dòng)完成
mBusy = false;
int first = view.getFirstVisiblePosition();
for (int i = 0; i < visi; i++) { // 設(shè)置所有可視條目Tag為null,條目將會(huì)自動(dòng)加載數(shù)據(jù)
TextView t = (TextView) view.getChildAt(i);
if (t.getTag() != null) {
t.setText(mStrings[first + i]);
t.setTag(null);
}
}break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: // 正在滾動(dòng)(手指未離開屏幕)
mBusy = true;
break;
case OnScrollListener.SCROLL_STATE_FLING: // 正在滾動(dòng)(手指已離開屏幕)
mBusy = true;
break;
}
}
復(fù)制代碼
在Adapter中根據(jù)mBusy狀態(tài),判斷是否立即加載數(shù)據(jù),重寫getView方法;
復(fù)制代碼
public View getView(int position, View convertView, ViewGroup parent) {
TextView text;
if (convertView == null) {
text = (TextView) mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
} else {
text = (TextView) convertView;
}
if (!mBusy) {
text.setText(mStrings[position]);
// Tag為空代表當(dāng)前View的數(shù)據(jù)已經(jīng)加載完成
text.setTag(null);
} else {
text.setText("Loading...");
// 非空的View代表當(dāng)前View仍然需要加載更多的數(shù)據(jù)
text.setTag("cc");
}
return text;
}
}
復(fù)制代碼
四、類似聊天記錄,自動(dòng)將新添加的項(xiàng)從底部添加并顯示到可見(jiàn)區(qū)域,主要是兩個(gè)屬性的設(shè)置,如下:
復(fù)制代碼
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:stackFromBottom="true" 自動(dòng)顯示到列表最底部
android:transcriptMode="normal" /> 設(shè)置當(dāng)顯示大量的條目時(shí),希望將最新的item顯示到可見(jiàn)區(qū)域
復(fù)制代碼
順便記錄一下輸入框點(diǎn)擊Enter事件,OnKeyListener(參照下面的代碼,可實(shí)現(xiàn)輸入新消息按下Enter并將新消息添加到列表底部);
復(fù)制代碼
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
// TODO
return true;
}
}
return false;
}
復(fù)制代碼
五、設(shè)置部分條目不可用:通常情況下,一個(gè)列表中的所有條目都可以使用,也即可以響應(yīng)點(diǎn)擊事件和有點(diǎn)擊的效果,但有的情況下,并不希望所有的條目都這樣,就可以自定義Adapter,通過(guò)條目的相關(guān)屬性判斷是否可用,(disEnabled狀態(tài)下,默認(rèn)的分割條不顯示)
復(fù)制代碼
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
// TODO 通過(guò)一定的判斷條件設(shè)置position條目可用
}
復(fù)制代碼
六、ListView點(diǎn)擊條目展開條目顯示更多信息:這種情況也是比較常見(jiàn)的,最多見(jiàn)的應(yīng)該是評(píng)論,一個(gè)評(píng)論列表,不同的人,評(píng)論的內(nèi)容長(zhǎng)度不同,如果全部顯示完,就會(huì)顯示得參差不齊,但又不能只顯示了部分,此時(shí)就得添加點(diǎn)擊條目查看更多的功能了;
簡(jiǎn)單說(shuō)下思路:自定義一個(gè)View,繼承自FrameLayout,里面有兩個(gè)TextView,一個(gè)是單行的(singleLine),另外一個(gè)是多行的(wrap_content);公開一個(gè)方法設(shè)置多行的TextView的可見(jiàn)狀態(tài)為VISIBLE或者GONE,在ListView的ItemClick回調(diào)中設(shè)置當(dāng)列表?xiàng)l目未展開時(shí),點(diǎn)擊條目展開條目,也即顯示更多信息;當(dāng)列表是展開的,點(diǎn)擊收起條目;并且通知數(shù)據(jù)源改變:notifyDataSetChanged;
七、在二中說(shuō)了選中單項(xiàng)的高亮顯示,現(xiàn)在來(lái)看看多選的高亮顯示,同樣,多選我這里也知道兩種方法;
1、同二中第2種方法,定義一個(gè)selector,里面包含一個(gè)選擇狀態(tài)state_activited,將此drawable設(shè)置為L(zhǎng)istView的selector或者是直接設(shè)置為條目的背景;此種模式類似于4.0之后部分手機(jī)短信列表的長(zhǎng)按之后進(jìn)行選擇條目然后進(jìn)行操作刪除的效果;
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); // 設(shè)置選擇模式
lv.setMultiChoiceModeListener(new ModeCallback());
復(fù)制代碼
private class ModeCallback implements ListView.MultiChoiceModeListener {
public boolean onCreateActionMode(ActionMode mode, Menu menu) { // 在ActionBar上創(chuàng)建按鈕
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.list_select_menu, menu);
mode.setTitle("Select Items");
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
// TODO 點(diǎn)擊某一個(gè)按鈕的回調(diào)
}
return true;
}
public void onDestroyActionMode(ActionMode mode) {
}
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) { // 選擇項(xiàng)改變回調(diào)事件,通過(guò)此方法獲取選擇了哪些項(xiàng)
final int checkedCount = getListView().getCheckedItemCount();
}
}
}
復(fù)制代碼
2、第二種方法比較簡(jiǎn)單些,適用范圍更加廣泛,上一種方法在2.x的版本上運(yùn)行會(huì)出錯(cuò),因?yàn)镸ultiChoiceMode是高版本上的新的一個(gè)接口;對(duì)于低版本的手機(jī),下面這種方法更加適用(Item的背景或者selector同上);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
如果需要獲取此種方法的選擇項(xiàng),就需要在OnItemClickListener的回調(diào)方法中進(jìn)行判斷,即每點(diǎn)擊一項(xiàng),改變當(dāng)前checked的值,最后再獲取結(jié)果;
|
|