ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
Android群英传读书笔记(第四章) 书中的示例代码: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<listView.getChildCount();i++){ View view = listView.getChildAt(i); } ~~~ 7.处理空ListView: 先是layout的布局设置: ~~~ <FrameLayout 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" > <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView> <ImageView android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ic_launcher" /> </FrameLayout> ~~~ 然后是代码中: ~~~ 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<String>( 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(); } } ~~~ ~~~ <FrameLayout 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" android:orientation="vertical" tools:context=".MainActivity" > <android.widget.Toolbar android:id="@+id/tool_bar" android:layout_width="match_parent" android:layout_height="@dimen/abc_action_bar_default_height_material" android:background="#fff332" /> <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> ~~~ 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(); } });