《第一行代码》第三章的练习和总结。
建立Word类
public class Word { private String name; private String info; public Word(String name, String info){ this.name = name; this.info = info; } public String getName(){ return name; } public String getInfo(){ return info; } }
为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="wrap_content"> <Button android:id="@+id/word_info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp"/> <TextView android:id="@+id/word_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical"/> </LinearLayout>
创建自定义适配器,继承自ArrayAdapter,泛型指定Word类。
public class WordAdapter extends ArrayAdapter<Word> { private int resourceID; public WordAdapter(Context context, int textViewResourceID, List<Word> words){ super(context,textViewResourceID,words); resourceID=textViewResourceID; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { final Word word = getItem(position); final View view; ViewHolder viewHolder; //对getView进行判断,如果convertView为null,则使用LayoutInflator加载布局,如果不为null则直接对convertView进行重用。 if(convertView ==null){ //LayoutInflater的inflate()方法的三个参数(布局文件的ID,父布局,false代表layout属性生效,但不会为View添加父布局) view = LayoutInflater.from(getContext()).inflate(resourceID,parent,false); viewHolder = new ViewHolder(); viewHolder.wordName = view.findViewById(R.id.word_name); viewHolder.wordInfo = view.findViewById(R.id.word_info); //将ViewHolder储存在View中 view.setTag(viewHolder); }else{ view = convertView; //重新获取ViewHolder viewHolder = (ViewHolder) view.getTag(); } viewHolder.wordName.setText(word.getName()); viewHolder.wordInfo.setText(word.getName()); viewHolder.wordInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(view.getContext(), word.getInfo(), Toast.LENGTH_SHORT).show(); } }); /*TextView wordName = view.findViewById(R.id.word_name); Button wordInfo = view.findViewById(R.id.word_info); wordName.setText(word.getName()); wordInfo.setText(word.getName()); wordInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(view.getContext(), word.getInfo(), Toast.LENGTH_SHORT).show(); } });*/ return view; } //建立ViewHolder用于对控件的实例进行缓存,当convertView为null,创建ViewHolder对象并将控件实例存放在ViewHolder中,再调用setTag()方法储存ViewHolder到View中。以便之后取出,即无需再通过findViewById()的方式来获取控件实例。 class ViewHolder{ TextView wordName; Button wordInfo; } }
Activity中的内容
public class FourthActivity extends BasicActivity implements View.OnClickListener { private ProgressBar progressBar; private String[] fruitList = {"Apple","Banana","Cherry","Durian","Fig","Grape"}; private List<word> wordList = new ArrayList<>(); public static void actionStart(Context context){ Intent intent = new Intent(context,FourthActivity.class); context.startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fourth); ListView listView1 =findViewById(R.id.listView1); ListView listView2 =findViewById(R.id.listView2); initWords(); WordAdapter wordAdapter = new WordAdapter(FourthActivity.this,R.layout.word_item,wordList); final ArrayAdapter fruitAdapter = new ArrayAdapter<string>(FourthActivity.this,android.R.layout.simple_list_item_1,fruitList); listView1.setAdapter(wordAdapter); listView2.setAdapter(fruitAdapter); listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Toast.makeText(FourthActivity.this,fruitList[position],Toast.LENGTH_SHORT).show(); } }); } private void initWords(){ Word a = new Word("AAA","This is word A."); wordList.add(a); Word b = new Word("BBB","This is word B."); wordList.add(b); Word c = new Word("CCC","This is word C."); wordList.add(c); Word d = new Word("DDD","This is word D."); wordList.add(d); Word e = new Word("EEE","This is word E."); wordList.add(e); Word f = new Word("FFF","This is word F."); wordList.add(f); Word g = new Word("GGG","This is word G."); wordList.add(g); Word h = new Word("HHH","This is word H."); wordList.add(h); Word i = new Word("III","This is word I."); wordList.add(i); Word j = new Word("JJJ","This is word J."); wordList.add(j); } }</string></word>
实现了两个ListView,上半部分为带Button自定义布局,下部分实现了setOnItemClickListener为ListView注册了监听器。
但是注意到,如果给上半部分实现了自定义布局的ListView添加setOnItemClickListener,点击自定义布局中的Button就无效,想让Button能够被点击,具体实现较为麻烦,而RecyclerView直接摈弃了点击事件的监听器,点击事件由具体View注册,避免了这个问题。
