书中的示例代码:github

本章主要讲了一些关于ListView的优化

关于ViewHolder的使用:略(这个太简单了)。不过要注意使用ViewHolder做缓存以后,在getView的方法中无论这项的每个视图是否需要设置属性(比如TextView设置的属性可能为null,item的某一个按钮的背景为透明、某一项的颜色为透明等),都需要为每一项的所有视图设置属性(textview的属性为空也需要设置setText(""),背景透明也需要设置),否则在滑动的过程中会出现内容的显示错乱。

2.设置项目间的分割线:

android:divider="@android:color/darker_gray"

android:dividerHeight="5dp"

如果不需要分割线可以如此:

android:divider="@null"

3.滚动条的隐藏:

android:scrollbars="none"

4.取消item的点击效果:

android:listSelector="#00000000"

5.设置ListView显示第几项:

listView.setSelection(n);//这个方法和scollTo类似,是瞬间完成移动

listView.smoothScrollBy(distance,duration);//下面三个为平滑移动

listView.smoothScrollByOffset(offset);

listView.smoothScrollToPosition(index);

6.遍历ListView中所有item:

for(int i=0,i

View view = listView.getChildAt(i);

}

7.处理空ListView:

先是layout的布局设置:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/lv"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/empty_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:src="@drawable/ic_launcher" />

然后是代码中:

listView.setEmptyView(findViewById(R.id.empty_view));

//设置以后ListView会根据是否有数据来判断是否显示该EmptyView。

8.ListView滑动监听:

OnTouchListener:

listView.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

// 触摸时操作

break;

case MotionEvent.ACTION_MOVE:

// 移动时操作

break;

case MotionEvent.ACTION_UP:

// 离开时操作

break;

}

return false;

}

});

OnScrollListener:

listView.setOnScrollListener(new OnScrollListener() {

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

switch (scrollState) {

case OnScrollListener.SCROLL_STATE_IDLE:

//滑动停止时

break;

case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:

//正在滚动时

break;

case OnScrollListener.SCROLL_STATE_FLING:

//手指快速滑动,手指离开后会因惯性继续滑动时

break;

}

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

//firstVisibleItem 当前能看到的第一个item的id,从0开始,包括显示不完整的

//visibleItemCount 当前能看见的item总数,包括显示不完整的

//totalItemCount listview的item总数

//滚动时一直调用

if(firstVisibleItem+visibleItemCount==totalItemCount&&totalItemCount>0){

//滚动至最后一行

}

if(firstVisibleItem> lastVisibleItem){

//上滑

}else if(firstVisibleItem< lastVisibleItem){

//下滑

}

lastVisibleItem=firstVisibleItem;//自行定义一个lastVisibleItem的成员变量

listView.getFirstVisiblePosition();

listView.getLastVisiblePosition();//当然也可以通过ListView提供的方法直接获取

}

});

9.具有弹性的ListView:

private int mMaxOverDistance=20;

/*

* 继承ListView重写overScrollBy,然后根据自己需求将maxOverScrollY设置为某个值即可,也可利用代码获取屏幕密度与该值相乘来适配屏幕

*/

@Override

protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,

int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {

return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,

mMaxOverDistance, isTouchEvent);

}

10.自动显示和隐藏布局的ListView:

public class MainActivity extends AppCompatActivity {

private Toolbar mToolbar;

private ListView mListView;

private String[] mStr = new String[20];

private int mTouchSlop;

private float mFirstY;

private float mCurrentY;

private int direction;

private ObjectAnimator mAnimator;

private boolean mShow = true;

View.OnTouchListener myTouchListener = new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mFirstY = event.getY();

break;

case MotionEvent.ACTION_MOVE:

mCurrentY = event.getY();

if (mCurrentY - mFirstY > mTouchSlop) {

direction = 0;// down

} else if (mFirstY - mCurrentY > mTouchSlop) {

direction = 1;// up

}

if (direction == 1) {

if (mShow) {

toolbarAnim(1);//show

mShow = !mShow;

}

} else if (direction == 0) {

if (!mShow) {

toolbarAnim(0);//hide

mShow = !mShow;

}

}

break;

case MotionEvent.ACTION_UP:

break;

}

return false;

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();

mToolbar = (Toolbar) findViewById(R.id.tool_bar);

mListView = (ListView) findViewById(R.id.lv);

for (int i = 0; i < mStr.length; i++) {

mStr[i] = "Item " + i;

}

View header = new View(this);

header.setLayoutParams(new AbsListView.LayoutParams(

AbsListView.LayoutParams.MATCH_PARENT,

(int) getResources().getDimension(R.dimen.abc_action_bar_default_height_material)));

mListView.addHeaderView(header);

mListView.setAdapter(new ArrayAdapter(

this,

android.R.layout.simple_list_item_1,

mStr));

mListView.setOnTouchListener(myTouchListener);

}

private void toolbarAnim(int flag) {

if (mAnimator != null && mAnimator.isRunning()) {

mAnimator.cancel();

}

if (flag == 0) {

mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), 0);

} else {

mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());

}

mAnimator.start();

}

}

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context=".MainActivity" >

android:id="@+id/tool_bar"

android:layout_width="match_parent"

android:layout_height="@dimen/abc_action_bar_default_height_material"

android:background="#fff332" />

android:id="@+id/lv"

android:layout_width="match_parent"

android:layout_height="match_parent" />

11.聊天ListView,这里直接贴关键代码:

这里主要重写BaseAdapter中的几个方法

@Override

public int getViewTypeCount() {

return 2;

}

@Override

public int getItemViewType(int position) {

return mChatBeanList.get(position).getType();

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder viewHolder;

ChatBean chatBean = mChatBeanList.get(position);

if (convertView == null) {

viewHolder = new ViewHolder();

if (getItemViewType(position) == 0) {// 不重写方法直接用ChatBean里的type比较也一样

convertView = View.inflate(getActivity(), R.layout.chat_item_in, null);

viewHolder.tv = (TextView) convertView.findViewById(R.id.tv_in_text);

} else {

convertView = View.inflate(getActivity(), R.layout.chat_item_out, null);

viewHolder.tv = (TextView) convertView.findViewById(R.id.tv_out_text);

}

convertView.setTag(viewHolder);

} else {

viewHolder = (ViewHolder) convertView.getTag();

}

viewHolder.tv.setText(chatBean.getText());

return convertView;

}

12动态改变ListView布局:

//在BaseAdapter里增加一个currentItem属性,通过它与position比较来判断哪个被选中

@Override

public View getView(int position, View convertView, ViewGroup parent) {

LinearLayout layout = new LinearLayout(getActivity());

layout.setOrientation(LinearLayout.VERTICAL);

if(currentItem==position){

layout.addView(addFocusView());

}else{

layout.addView(addNormalView(position));

}

return layout;

}

//在ListView的item点击事件设置点击中的item并且刷新ListView数据

mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView> parent, View view, int position, long id) {

mAdapter.setCurrentItem(position);

mAdapter.notifyDataSetChanged();

}

});

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐