ListView使用方法大總結
Adapter一般有以下的幾種實現類:ArrayAdapter,SimpleAdapter,SimpleCursorAdapter,BaseAdapter。
ArrayAdapter的每一個列表只能是一個TextView,ArrayAdapter的使用方法如下:
ArrayAdapter adapter=new ArrayAdapter(Context,一個TextView佈局,String 陣列);
SimpleAdapter常常用來實現
這種的介面。
使用和方法如下:
SimpleAdapter simpleAdapter=new SimpleAdapter(Context,一個List<?extends Map<String,?>>型別的集合物件,佈局,String[]型別的引數,數組裡邊存放Map裡邊的鍵值,int[]型別的引數,數組裡邊存放item中每一個元件的id號)
下面來介紹以下BaseAdapter的使用技巧:
1.使用ViewHolder
viewHolder一般定義在Adapter的內部,並且將佈局中的控制元件作為成員變數。
public class ViewHolderAdapter extends BaseAdapter { private List<String> mData; private LayoutInflater mInflater; @Override public int getCount() { return mData.size(); } @Override public Object getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder=null; if (convertView==null){ holder=new ViewHolder(); convertView=mInflater.inflate(R.layout.viewholder_item,null); holder.img= (ImageView) convertView.findViewById(R.id.imageview); holder.title= (TextView) convertView.findViewById(R.id.textview); convertView.setTag(holder); } else{ holder= (ViewHolder) convertView.getTag(); } holder.img.setBackgroundResource(R.drawable.ic_launcher); holder.title.setText(mData.get(position)); return convertView; } public ViewHolderAdapter(List<String> mData, Context context) { this.mData = mData; mInflater=LayoutInflater.from(context); } <span style="color:#FF0000;">public final class ViewHolder{ public ImageView img; public TextView title; } </span>}
以下是ListView的一些設定:public class MainActivity extends AppCompatActivity { private ListView myList; private ArrayList<String> mData=new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myList= (ListView) findViewById(R.id.myList); for(int i=0;i<50;i++){ mData.add("item"+i); } ViewHolderAdapter myHolderAdapter=new ViewHolderAdapter(mData,this); myList.setAdapter(myHolderAdapter); //動態新增ListView mData.add("新的一項"); myHolderAdapter.notifyDataSetChanged(); myList.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch(scrollState){ case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: //滑動停止的時候 Log.d("TEST","SCROLL_STATE_IDLE"); break; case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: //正在滾動 Log.d("TEST","SCROLL_STATE_TOUCH_SCROLL"); break; case AbsListView.OnScrollListener.SCROLL_STATE_FLING: //手指拋開以後,Listview依靠慣性滑動的時候會回撥這個方法 Log.d("TEST","SCROLL_STATE_FLING"); break; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //滾動的時候會一直呼叫 Log.d("TEST","正在滾動"); } }); } }
設定專案分割線:
android:divider="@android:color/darker_gray"
android:dividerHeight="10dp"
隱藏ListView的滾動條;
android:scrollbars="none"
設定ListView的Item點選效果:
android:listSelector="RGB值"
設定ListView顯示在第幾頁:
listView.setSelection(N);
listview平滑顯示:
mListView.smoothScro;lBy(distance,duiration);
mListView.smoothScrollByoffset(offset);
mListView.smoothScrollToPosition(index);
實現具有彈性的ListView(下拉到最下面或者上拉到最上邊ListView可以繼續滑行一段距離)
首先定義一個ListView:
public class MyListView extends ListView{
private int mMaxOvewDistance=100;
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics metrics=context.getResources().getDisplayMetrics();
float density=metrics.density;
mMaxOvewDistance=(int) (density*mMaxOvewDistance);
}
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
<span style="color:#FF0000;">@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,<span style="color:#3333FF;">mMaxOvewDistance</span>, isTouchEvent);
}</span>
}
重寫overScrollBy這個方法,上邊藍色的部分的引數表示可以沿著Y軸滑動的距離。
這裡還在ListView的構造方法中做了一個處理,主要就是為了適配各種畫素密度的螢幕,具有更好的相容性。
實現ToolBar自動隱藏的ListView:
這裡我們會使用到ToolBar,所以我們先定義一個ToolBar:
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toolbar"
android:background="@color/colorAccent">
</android.support.v7.widget.Toolbar>
下面貼出主程式:public class MainActivity extends AppCompatActivity {
private int scaledTouchSlop;
private float firstY = 0;
private Toolbar toolbar;
private ObjectAnimator animtor;
private ListView myList;
private ArrayList<String> mData=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myList= (ListView) findViewById(R.id.myList);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
for(int i=0;i<50;i++){
mData.add("item"+i);
}
ViewHolderAdapter myHolderAdapter=new ViewHolderAdapter(mData,this);
initHeadView();//初始化
myList.setAdapter(myHolderAdapter);
scaledTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();//滑動的最小距離
myList.setOnTouchListener(new View.OnTouchListener() {
private float currentY;
private int direction;
private boolean mShow = true;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
firstY=event.getY();
break;
case MotionEvent.ACTION_MOVE:
currentY=event.getY();
if ((currentY-firstY)>scaledTouchSlop){
direction=0;
}else if((firstY-currentY)>scaledTouchSlop){
direction=1;
}
if(direction==1){
if (mShow){
toolbarAnim(1);
mShow=!mShow;
}
}
else if (direction==0){
toolbarAnim(0);
mShow=!mShow;
}
break;
}
return false;
}
});
}
public void initHeadView(){
View view = new View(this);
AbsListView.LayoutParams params = new AbsListView.LayoutParams
(AbsListView.LayoutParams.MATCH_PARENT,
(int)getResources().getDimension(R.dimen.abc_action_bar_default_height_material));
view.setLayoutParams(params);
myList.addHeaderView(view);
}
public void toolbarAnim(int direction){
//開始新的動畫之前要先取消以前的動畫
if(animtor!=null&&animtor.isRunning()){
animtor.cancel();
}
if(direction == 0){//手指向下滑動,顯示ToolBar
//toolbar.getTranslationY()獲取的是Toolbar距離自己頂部的距離
animtor = ObjectAnimator.ofFloat(toolbar, "translationY", toolbar.getTranslationY(), 0);
}else if( direction == 1){
animtor = ObjectAnimator.ofFloat(toolbar, "translationY", toolbar.getTranslationY(), -toolbar.getHeight());
}
animtor.start();
}
}
這裡講一下ofFoat方法中幾個引數的意義:
ofFloat()方法的第一個引數表示動畫操作的物件(可以是任意物件),第二個引數表示操作物件的屬性名字(只要是物件有的屬性都可以),第三個引數之後就是動畫過渡值。當然過度值可以有一個到N個,如果是一個值的話預設這個值是動畫過渡值的結束值。如果有N個值,動畫就在這N個值之間過渡。
實現對話方塊ListView:
首先我們需要寫兩個對話方塊的佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="left"
android:padding="10dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/icon_in"
android:src="@drawable/ic_launcher"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_in"
android:background="@drawable/chatitem_out_bg"
android:layout_marginLeft="10dp"
android:gravity="center"
android:textSize="16sp"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="10dp"
android:gravity="right">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_out"
android:background="@drawable/chatitem_in_bg"
android:gravity="center"
android:layout_marginRight="10dp"
android:textSize="16sp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/icon_out"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
然後實現完成BaseAdapter,在getView中進行佈局型別的判斷
下面貼出主程式
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView= (ListView) findViewById(R.id.mylistview);
mListView.setDivider(null);//去除下劃線
ChatItemListViewBean bean1=new ChatItemListViewBean();
bean1.setType(0);
bean1.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher));
bean1.setText("啊啊啊");
ChatItemListViewBean bean2=new ChatItemListViewBean();
bean2.setType(1);
bean2.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher));
bean2.setText("好好好");
List<ChatItemListViewBean> data=new ArrayList<ChatItemListViewBean>();
data.add(bean1);
data.add(bean2);
mListView.setAdapter(new ChatItemListViewAdapter(data,this));
}
顯示效果:
這裡需要注意getItemViewType和getViewTypeCount這兩個函式,getViewTypeCount這個方法告訴ListView我共有多少種item,getItemViewType方法告訴ListView每行該顯示哪種item,並且該方法中返回的type型別必須為整數且不能大於getViewTypeCount返回的數。
動態改變ListView的佈局:
當點選了Item時,其佈局檔案發生改變來達到一個Focus的效果。一般有兩種方法。一種是將兩種佈局檔案寫在一起,通過控制佈局的顯示。隱藏,來達到切換佈局的效果;另一種則是在getView()的時候,通過判斷來選擇載入不同的佈局,這樣就要在每次點選操作後重新整理佈局,重寫呼叫getView(),使用notifyDataSetChanged()方法來實現。
這裡選擇後面一種方法來實現動態改變ListView的佈局。
首先還是實現Adapter下面貼出程式碼:
Adapter中有兩個重要的方法,addFocusView和addNormalView,前者只是載入一個ImageView,後者要載入另外一個佈局,這個佈局包括一個ImageView,一個TextView,然後在getview這個函式中進行判斷,如果哪個Item被點選了,就把當前的這一欄改成FocusView。當然getview只能在初始化的時候進行呼叫,我們在MainActivity中對ITem設定監聽,在listview被點選的時候,呼叫notifyDataSetChanged()方法來實現資料重新整理的功能。
public class dymicAdapter extends BaseAdapter{
private List<String> mData;
private Context mContext;
private int mCurrentItem=0;//<span style="font-size:10px;">預設是第一個Item</span>
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout layout=new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
if(mCurrentItem==position){
layout.addView(addFocusView(position));
}
else{
layout.addView(addNormalView(position));
}
return layout;
}
public void setCurrentItem(int currentItem) {
this.mCurrentItem = currentItem;
}
public dymicAdapter(List<String> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
private View addFocusView(int i){
ImageView iv=new ImageView(mContext);
iv.setImageResource(R.drawable.ic_launcher);
return iv;
}
private View addNormalView(int i){
LinearLayout layout=new LinearLayout(mContext);
layout.setOrientation(LinearLayout.HORIZONTAL);
ImageView iv=new ImageView(mContext);
iv.setImageResource(R.drawable.in_icon);
layout.addView(iv,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));
TextView tv=new TextView(mContext);
tv.setText(mData.get(i));
layout.addView(tv,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));
layout.setGravity(Gravity.CENTER);
return layout;
}
}
下面是MainActivity的主程式:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView myListView= (ListView) findViewById(R.id.mylistview);
List<String> data=new ArrayList<String>();
for(int i=0;i<50;i++){
data.add("Item"+i);
}
final dymicAdapter myadapter=new dymicAdapter(data,this);
myListView.setAdapter(myadapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
myadapter.setCurrentItem(position);
myadapter.notifyDataSetChanged();//通知介面進行更新
}
});
}
下面是實驗結果: