Android中ListView與RecyclerView的詳解與使用【附Project壓縮包】
ListView簡介
ListView可以用來展示數據的控件,最熟悉的像qq裏的好友列表,就可以通過Listview來實現。ListView可以理解爲一個由很多行view組成的列表,而view通過綁定item改變自身的樣式。
ListView的最簡單的使用
一:在activiy_main.XML中寫入一個ListView
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/l_1"/>
二:在MainActivity中聲明數據,這裏以一組String數據爲例
private String[] data = {"1", "2", "3", "4", "5"};
三:構造適配器,這裏的適配器泛型指向String類型,item是系統內置的item
ArrayAdapter<String> adapter=new ArrayAdapter<String>
(MainActivity.this,android.R.layout.simple_list_item_1,data);
四:Listview傳入適配器
ListView listView=(ListView)findViewById(R.id.l_1);//ListView的id
listView.setAdapter(adapter);
是不是非常簡單?但是這只是最基本的使用,沒有經過任何的優化。
ListView的優化
顯然一個listview只能顯示文字是非常單調的
一:指定自己設置的item
新建一個item.xml,寫入一個Button和ImageView
<ImageView
android:id="@+id/fruit_image"
android:layout_width="80dp"
android:layout_height="80dp" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp" />
二:新建一個類(以水果類爲例)
public class fruit {
private String name;
private int imageId;
public fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}
三 :有了水果類,,因爲原本的ArrayAdapter已經無法滿足水果類傳入ListView的要求了,需要一個新的適配器。註釋的部分代碼是運行效率優化前的代碼,當ListView是滾動時,原來的代碼會就不斷地讀取item的佈局和id,修改後的代碼會將讀取的佈局和id存儲在緩存內,需要時再拿出來使用。
public FA(Context context, int textViewResourceId, List<fruit> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
fruit fruit = getItem(position);
// View view= LayoutInflater.from(getContext()).inflate(resourceId,parent,false);//可以優化,優化部分如下
View view;//避免重新加載佈局
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
viewHolder = new ViewHolder();
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
view.setTag(viewHolder);
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
// ImageView fruitImage=(ImageView)view.findViewById(R.id.fruit_image);
// TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);
// fruitImage.setImageResource(fruit.getImageId());
// fruitName.setText(fruit.getName());
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());//避免重新讀取fruitname和fruitIamge,將這兩個信息存儲在viewholderr中,再將viewholder放置在view的標籤內
return view;
}
class ViewHolder {
ImageView fruitImage;
TextView fruitName;
}
}
四:傳入ListView並添加點擊事件
private List<fruit> fruitlist = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inintfruit();//初始化水果列表
FA adapter = new FA(MainActivity.this, R.layout.fruit_item, fruitlist);
ListView listView = (ListView) findViewById(R.id.l_1);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {//item點擊事件
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
fruit fruit = fruitlist.get(position);
Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
listView.setAdapter(adapter);//傳入adapter
}
private void inintfruit() {//準備的圖片太少,只能循環已到達滾動的 目的
for (int i = 0; i < 5; i++) {//圖片在項目中有
fruit apple = new fruit("Apple", R.drawable.apple_pic);
fruitlist.add(apple);
fruit banana = new fruit("banana", R.drawable.banana_pic);
fruitlist.add(banana);
fruit orange = new fruit("orange", R.drawable.orange_pic);
fruitlist.add(orange);
}
}
最終的效果如下
RecyclerView
RecyclerView比ListView好,好在哪幾個地方呢?
一:ListView能實現的RecyclerView也能實現
二:除了一,它還能實現橫向滾動,瀑布流滾動(類似於淘寶的瀏覽界面)
三:它的點擊方法通過view實現,這就意味之能更方便的實現點擊子項裏的某一個控件(例如Image和TextView)
RecyclerView的簡單使用(其實一點也不簡單)
一:最關鍵的一步,當然是引入包了。把下面這行代碼添加到build.gradle的dependencies 中,然後同步一下(點擊右上角的Sync now)
implementation ‘androidx.recyclerview:recyclerview:1.0.0’//添加recyclerview.jar包
二:在activity_main.xml中添加一個RecyclerView界面
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyle_view"></androidx.recyclerview.widget.RecyclerView>
三:把之前ListView的item.xml和Fruit類copy過來,圖片也複製過來(能copy絕對不寫)
四:創建適配器並在適配器中實現點擊事件和加載item佈局。這個適配器很好理解,就是代碼多了點
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruit> mFruitList;
class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitaName;
public ViewHolder(View view) {
super(view);
fruitView=view;
fruitaName = (TextView) view.findViewById(R.id.fruit_name);
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);//傳入item佈局
final ViewHolder holder=new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {//view的點擊事件
@Override
public void onClick(View v) {
int postion=holder.getAdapterPosition();
Fruit fruit=mFruitList.get(postion);
Toast.makeText(v.getContext(),"you clicked view"+fruit.getName(),Toast.LENGTH_SHORT).show();
}
});
//ViewHolder holder=new ViewHolder(view);
holder.fruitImage.setOnClickListener(new View.OnClickListener() {//item裏的圖片點擊事件
@Override
public void onClick(View v) {
int postion=holder.getAdapterPosition();
Fruit fruit=mFruitList.get(postion);
Toast.makeText(v.getContext(),"you clicked image"+fruit.getName(),Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit=mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitaName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
五:修改MainActivity裏的代碼,主要目的有三個,指定RecyclerView的佈局(瀑布流佈局),聲明一個適配器,傳入適配器到RecyclerView中
private List<Fruit> fruitList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruit();
RecyclerView recyclerView =(RecyclerView)findViewById(R.id.recyle_view);
// LinearLayoutManager layoutManager=new LinearLayoutManager(this);//縱/橫向佈局
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);//三列的瀑布流佈局
// layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);//改爲縱向佈局
FruitAdapter adapter=new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruit(){
for (int i=0;i<5;i++) {
Fruit apple =new Fruit(getRandomLengthName("Apple"),R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana =new Fruit(getRandomLengthName("Banana"),R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange =new Fruit(getRandomLengthName("Orange"),R.drawable.orange_pic);
fruitList.add(orange);
}
}
private String getRandomLengthName(String name){//這一段的目的是爲了將一些文字重複以證明瀑布流佈局的是真的三列。
Random random =new Random();
int length=random.nextInt(20)+1;
StringBuilder builder=new StringBuilder();
for (int i=0;i<length;i++){
builder.append(name);
}
return builder.toString();
}
然後最終效果如下
點擊(View時)