Android:日常學習筆記(8)———探究UI開發(5)
ListView控件的使用
ListView概述
A view that shows items in a vertically scrolling list. The items come from the?ListAdapter
?associated with this view.
1.關于ArrayAdapter:
ArrayAdapter<T> 是 ListAdapter的直接子類:一個由任意對象數組支持的具體的BaseAdapter。
一個支持任意對象數組的具體的BaseAdapter。默認情況下,這個類期望提供的資源id引用一個TextView。如果你使用更加復雜的布局, 使用需要字段id的構造函數。?That field id should reference a TextView in the larger layout resource.
However the TextView is referenced, it will be filled with the toString() of each object in the array. You can add lists or arrays of custom objects. Override the toString() method of your objects to determine what text will be displayed for the item in the list.
To use something other than TextViews for the array display, for instance, ImageViews, or to have some of data besides toString() results fill the views, override?
getView(int, View, ViewGroup)
?to return the type of view you want.
2.關于getView(int, View, ViewGroup)
獲得一個可以在指定位置顯示數據集中數據的視圖。你可以手動創作一個視圖也可以加載XML中的視圖。?When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use?
inflate(int, android.view.ViewGroup, boolean)
?to specify a root view and to prevent attachment to the root. ?
ListView的簡單用法
public class MainActivity extends AppCompatActivity {private String[] data={"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry",
"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry",
"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ArrayAdapter<String> adapter = new ArrayAdapter<String>
(MainActivity.this,R.layout.support_simple_spinner_dropdown_item,data);ListView listView = (ListView) findViewById(R.id.list_view);listView.setAdapter(adapter);} }
說明:
ArrayAdapter通過泛型來指定要適配的數據類型,然后在構造函數中把當前上下文、ListView子項布局的ID、要適配的數據傳入。
我們在這里使用了安卓的內置布局文件。
ListView設置適配器,setAdapter(),將構建好的適配器對象傳進去,以此建立數據與ListView之間的關系。
定制ListView界面
1.定義一個實體類
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 void setName(String name) {this.name = name;}public int getImageID() {return imageID;}public void setImageID(int imageID) {this.imageID = imageID;} }
2.自定義子項布局文件
<?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"><ImageViewandroid:id="@+id/fruit_img"android:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid:id="@+id/fruit_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"/> </LinearLayout>
3.編寫適配類
public class FruitAdapter extends ArrayAdapter<Fruit> {private int resourceID;public FruitAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull List<Fruit> objects) {super(context, resource, textViewResourceId, objects);resourceID = textViewResourceId;}@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {Fruit fruit = getItem(position);View view = LayoutInflater.from(getContext()).inflate(resourceID,parent,false);ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_img);TextView fruitText = (TextView) view.findViewById(R.id.fruit_text);fruitImage.setImageResource(fruit.getImageID());fruitText.setText(fruit.getName());return view;} }
4.應用
public class MainActivity extends AppCompatActivity {private List<Fruit> fruitList=new ArrayList<>();protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initFruits();FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.activity_main,R.layout.entry_fruit_item,fruitList);ListView listView = (ListView) findViewById(R.id.list_view);listView.setAdapter(adapter);}public void initFruits(){for(int i=0;i<100;i++){fruitList.add(new Fruit("XXX",R.drawable.next_24px));}} }
?提升ListView的運行效率
1.避免重復加載布局文件
在getView中加入如下代碼:
//convertView用于將之前加載好的布局進行緩存,這里進行判斷,避免重復加載。if(convertView==null)view = LayoutInflater.from(getContext()).inflate(resourceID,parent,false);elseview =convertView;
2.避免重復查找控件
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {Fruit fruit = getItem(position);View view;ViewHolder viewHolder;//convertView用于將之前加載好的布局進行緩存,這里進行判斷,避免重復加載。if(convertView==null){view = LayoutInflater.from(getContext()).inflate(resourceID,parent,false);viewHolder= new ViewHolder();viewHolder.fruitImage=(ImageView) view.findViewById(R.id.fruit_img);viewHolder.fruitText=(TextView) view.findViewById(R.id.fruit_text);view.setTag(viewHolder);}else{view =convertView;viewHolder= (ViewHolder) view.getTag();}viewHolder.fruitImage.setImageResource(fruit.getImageID());viewHolder.fruitText.setText(fruit.getName());return view;}
//用于對控件的實例進行緩存class ViewHolder{ImageView fruitImage;TextView fruitText;} }
ListView的點擊事件
FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.activity_main,R.layout.entry_fruit_item,fruitList);ListView listView = (ListView) findViewById(R.id.list_view);listView.setAdapter(adapter);listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {public void onItemClick(AdapterView<?> parent, View view, int position, long id) {Fruit fruit = fruitList.get(position);Toast.makeText(MainActivity.this,fruit.getName(),Toast.LENGTH_LONG).show();}});
RecyclerView
使用RecyclerView
1.在build.gradle添加相應的依賴庫
2.點擊Sync Now進行同步。
3.修改XML布局文件
簡單使用
1.編寫適配器
public class FruitRecyclerAdapter extends RecyclerView.Adapter<FruitRecyclerAdapter.viewHolder> {private List<Fruit> fruitList;static class viewHolder extends RecyclerView.ViewHolder{ImageView fruitImage;TextView fruitText;public viewHolder(View itemView) {super(itemView);fruitImage = (ImageView) itemView.findViewById(R.id.fruit_img);fruitText = (TextView) itemView.findViewById(R.id.fruit_text);}}@Overridepublic viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.entry_fruit_item,parent,false);viewHolder viewHolder = new viewHolder(view);return viewHolder;}//在每一個子項被滾動到屏幕內時執行 @Overridepublic void onBindViewHolder(viewHolder holder, int position) {Fruit fruit = fruitList.get(position);holder.fruitText.setText(fruit.getName());holder.fruitImage.setImageResource(fruit.getImageID());}@Overridepublic int getItemCount() {return fruitList.size();}public FruitRecyclerAdapter(List<Fruit> fruitList) {this.fruitList = fruitList;} }
?2.應用
public class RecyclerListActivity extends AppCompatActivity {private List<Fruit> fruitList =new ArrayList<>();protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initData();setContentView(R.layout.activity_recycler_list);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_view);LinearLayoutManager layoutManager = new LinearLayoutManager(this);recyclerView.setLayoutManager(layoutManager);FruitRecyclerAdapter fruitRecyclerAdapter = new FruitRecyclerAdapter(fruitList);recyclerView.setAdapter(fruitRecyclerAdapter);}public void initData(){for(int i=0;i<30;i++){Fruit fruit = new Fruit("XXX",R.drawable.next_24px);fruitList.add(fruit);}} }
?
實現橫向滾動
1.修改布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="100dp"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/fruit_img"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/next_24px"android:layout_gravity="center_horizontal"/><TextViewandroid:id="@+id/fruit_text"android:text="XXXXX"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal" /> </LinearLayout>
效果如右圖所示:
?2.在布局管理器中設置布局排布方式為水平
。。。protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initData();setContentView(R.layout.activity_recycler_list);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_view);LinearLayoutManager layoutManager = new LinearLayoutManager(this);layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);recyclerView.setLayoutManager(layoutManager);FruitRecyclerAdapter fruitRecyclerAdapter = new FruitRecyclerAdapter(fruitList);recyclerView.setAdapter(fruitRecyclerAdapter);} 。。。
說明:
ListView的布局排列規則是由自己管理的,而RecyclerView則將這個工作交給了布局管理器,LayoutManager中置頂了一套可擴展的布局排列接口,子類只要按照接口的規范來實現,就能制定出各種不同排列方式的布局了。
瀑布流布局
效果:
代碼:
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);recyclerView.setLayoutManager(layoutManager);
處理點擊事件
public viewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.entry_fruit_vertical_item,parent,false);final viewHolder viewHolder = new viewHolder(view); viewHolder.fruitView.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {int position = viewHolder.getAdapterPosition();Fruit fruit = fruitList.get(position);Toast.makeText(parent.getContext(),fruit.getName(),Toast.LENGTH_LONG).show(); }});return viewHolder;}
說明:
RecyclerView的強大之處在于,他可以輕松實現子項中任意控件或布局的點擊事件。
小結
?
?
?
?
?
?