ListView的使用範圍非常廣泛,儘管RecycleView在很多地方取代了ListView,但是ListView的地位還是難以撼動的。
那麼這一章節的知識點,將通過代碼的方式展示出來:
ListView的重要屬性
<com.why.a4_listview.MyListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/**
* 這兩個屬性控制分割線和分割線的高度,
* android:divider="null"是把分割線設置爲了透明,也就是去掉了分割線
**/
android:divider="@android:color/darker_gray"
/**
* 取消進度條
**/
android:scrollbars="none"
/**
* 設置點擊listview的item的點擊效果,下面是使得點擊效果爲透明狀態,也就是取消了點擊效果
**/
android:listSelector="@android:color/transparent"
>
</com.why.a4_listview.MyListView>
ListView的使用
public class MainActivity extends Activity {
private List<ChatItemListViewBean> mChatData;;
private MyListView listView;
private List<String> mData;
private Toolbar mToolbar;
private int mTouchSlop;
private boolean mShow = true;
private float mFirstY;
private int direction;
private Animator mAnimator;
private View.OnTouchListener myTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.i("test", "ACTION_DOWN: ");
mFirstY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Log.i("test", "ACTION_MOVE: ");
float currentY = event.getY();
if (currentY - mFirstY > 0){
//向下滑動
direction = 0;
}else if (mFirstY - currentY > 0){
//向上滑動
direction = 1;
}
if (direction == 1){
if (mShow){
toolbarAnim(0);//隱藏
mShow = !mShow;
}
}else if (direction == 0){
if (!mShow){
toolbarAnim(1);//顯示
mShow = !mShow;
}
}
break;
case MotionEvent.ACTION_UP:
Log.i("test", "ACTION_UP: ");
break;
}
return false;
}
};
private void toolbarAnim(int flag) {
if (mAnimator != null && mAnimator.isRunning()){
mAnimator.cancel();
}
if (flag == 0){ //隱藏
//效果一樣
//mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", 0, -mToolbar.getHeight());
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());
}else { //顯示
//mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", -mToolbar.getHeight(), 0);
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), 0);
}
mAnimator.start();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initChat();
}
private void initChat() {
initToolBar();
mToolbar.setVisibility(View.GONE);
initChatData();
listView = (MyListView) findViewById(R.id.lv);
listView.setAdapter(new ChatListViewAdapter(getApplicationContext(), mChatData));
}
private void initText() {
initToolBar();
initData();
textListView();
initText();
}
private void initToolBar() {
mToolbar = findViewById(R.id.toolbar);
}
private void initData() {
mData = new ArrayList<>();
for (int i=0; i<20; i++){
mData.add(String.valueOf(i));
}
/**
* 獲得系統認爲的最低的滑動距離
*/
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
}
private void textListView() {
listView = (MyListView) findViewById(R.id.lv);
listView.setAdapter(new ViewHolderAdapter(getApplicationContext(), mData));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/**
* 瞬間移動到 position 爲11的item上,position 爲11的item出現在第一行
*/
//listView.setSelection(11);
/**
* 平滑移動到position爲20的item上,
* 但是當從上向下滑動的時候,20出現在屏幕的最後一行
* 從下向上滑動的時候,20出現在屏幕的第一行
*/
//listView.smoothScrollToPosition(20);
/**
* -25是指向上移動25個item, 25是指向下移動25個item
*/
//listView.smoothScrollByOffset(25);
/**
* 在2秒內向下移動500個px
*/
//listView.smoothScrollBy(500, 2000);
/**
* 獲取第20個子view
*/
//View childView = listView.getChildAt(20);
}
});
/**
* 當listview爲空數據的時候,要顯示的佈局
*/
if (mData.size() == 0){
listView.setEmptyView(findViewById(R.id.iv_empty));
}
listView.setOnTouchListener(new View.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;
}
});
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState){
/**
* 滑動停止
*/
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
Log.i("test", "滑動停止---SCROLL_STATE_IDLE: ");
break;
/**
* 正在滑動
*/
case SCROLL_STATE_TOUCH_SCROLL:
Log.i("test", "正在滑動---SCROLL_STATE_TOUCH_SCROLL: ");
break;
/**
* 手指用力滑動屏幕導致形成慣性的時候,此時手指離開屏幕後,listview由於慣性繼續滑動的時候走這裏
* 如果手指力道不能形成慣性,那麼當前方法只會調用兩次
* 如果足以形成慣性,會調用三次,而不是一直調用走這裏
*/
case SCROLL_STATE_FLING:
Log.i("test", "慣性滑動---SCROLL_STATE_FLING: ");
break;
}
}
/**
* 滾動時一直調用該方法
* firstVisibleItem 當前能看到的第一個item的id(從0開始)
* visibleItemCount 當前能看到的item的總數(沒有顯示完全的item也包含在內)
* totalItemCount 整個listview的item總數
*/
int lastVisibleItem;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
Log.i("test", "onScroll: ");
/**
* 判斷是否到了最後一行
*/
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0){
Log.i("test", "到底了: ");
}
if (firstVisibleItem > lastVisibleItem){
Log.i("test", "向上滑動: ");
}else if (firstVisibleItem < lastVisibleItem){
Log.i("test", "向下滑動: ");
}
lastVisibleItem = firstVisibleItem;
}
});
/**
* 獲取可視區域內第一個item的position
* 不滑動獲取到的值爲0
*/
int firstVisiblePosition = listView.getFirstVisiblePosition();
Log.i("test", "firstVisiblePosition: "+firstVisiblePosition);
/**
* 獲取可視區域內最後一個item的position
* 沒有滑動的時候,得到的值爲-1,原因getChildCount()獲取到的值爲0
*/
int lastVisiblePosition = listView.getLastVisiblePosition();
Log.i("test", "最後一個item: "+lastVisiblePosition);
addHeaderView();
listView.setOnTouchListener(myTouchListener);
}
/**
* 爲防止第一個元素被toolbar遮擋,應該添加頭部
*/
private void addHeaderView() {
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)));
listView.addHeaderView(header);
}
}
ListView彈性效果的設置
當上滑到頭或者下滑到底的時候,需要有個彈性效果,下面自定義的 ListView 能夠達到一個簡易的彈性效果。
public class MyListView extends ListView {
private int mMaxOverDistance = 300;
public MyListView(Context context) {
this(context, null);
}
public MyListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData(context);
}
/**
* 滿足多分辨率的要求,根據屏幕density來計算具體的值
* @param context
*/
private void initData(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float density = displayMetrics.density;
mMaxOverDistance = (int) (density*mMaxOverDistance);
}
/**
* 重寫該方法,在listview中maxOverScrollY的值默認爲0;
* 我將修改爲mMaxOverDistance。使得listview滑動到邊界的時候,能夠有mMaxOverDistance長的彈性效果
*
* 這是比較簡單的一種增加彈性效果的方式
*/
@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);
}
}