编辑
2020-11-19
客户端技术
00
请注意,本文编写于 1047 天前,最后修改于 113 天前,其中某些信息可能已经过时。

目录

ListView
ListView的基本使用
点击事件与长按事件
设置HeaderView与FooterView
ListView的优化
条目布局分类加载
CardView
CardView的常用属性
CardView使用示例
使用tools工具预览
Lombok在Android中的使用
编译时编码错误解决方案
Android屏幕适配

本篇文章主要是记录一下高级控件ListView和CardView的使用方式和注意事项,虽然目前都已经用RecyclerView替代了ListView但是了解其中的原理和优化还是有必要的,关于ListView的原理和真正意义上的优化在后面会专门写一片文章来讲述,本篇只谈其具体使用与必须优化的方式。至于CardView其实用的还是比较多的,可以看到我的小Demo实现的效果还是很不错!最后涉及到了一些Android屏幕适配问题的解决方案。

ListView

Displays a vertically-scrollable collection of views, where each view is positioned immediatelybelow the previous view in the list. For a more modern, flexible, and performant approach to displaying lists, use android.support.v7.widget.RecyclerView.

ListView的基本使用

ListView使用步骤如下:

1、在Layout中创建ListView 2、创建每一行的layout 3、创建每一行的数据 4、用adapter将数据填充到每一行的视图中

条目布局文件 item_app_list.xml

xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:orientation="horizontal"> <ImageView android:id="@+id/app_icon_iv" android:src="@mipmap/ic_launcher" android:layout_width="40dp" android:layout_height="40dp"/> <TextView android:id="@+id/app_name_tv" android:textSize="20sp" android:paddingLeft="10dp" android:gravity="center_vertical" android:text="@string/app_name" android:layout_width="match_parent" android:layout_height="40dp"/> </LinearLayout>

AppListActivity.java

java
public class AppListActivity extends AppCompatActivity { private List<String> appNameList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_list); ListView listView = findViewById(R.id.app_lv); appNameList = Arrays.asList("QQ", "微信", "牛客", "招商银行", "支付宝"); //listView.setAdapter(new AppListAdapterBase()); listView.setAdapter(new AppListAdapter(getAppInfo())); } // 获取所有的应用信息 private List<ResolveInfo> getAppInfo(){ Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); return getPackageManager().queryIntentActivities(intent, 0); } public class AppListAdapter extends BaseAdapter { private List<ResolveInfo> resolveInfoList; public AppListAdapter(List<ResolveInfo> appInfo) { this.resolveInfoList = appInfo; } @Override public int getCount() { return resolveInfoList.size(); } @Override public Object getItem(int position) { return resolveInfoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.item_app_list, null); ImageView iv = convertView.findViewById(R.id.app_icon_iv); TextView tv = convertView.findViewById(R.id.app_name_tv); ResolveInfo resolveInfo = resolveInfoList.get(position); tv.setText(resolveInfo.activityInfo.loadLabel(getPackageManager())); iv.setImageDrawable(resolveInfo.activityInfo.loadIcon(getPackageManager())); // 在这里给每一个条目设置点击事件 convertView.setOnClickListener((v) -> { String packageName = resolveInfo.activityInfo.packageName; String className = resolveInfo.activityInfo.name; ComponentName componentName = new ComponentName(packageName, className); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent); }); return convertView; } } // 最基础的数据展示,ImageView是固定的 public class AppListAdapterBase extends BaseAdapter { @Override public int getCount() { return appNameList.size(); } @Override public Object getItem(int position) { return appNameList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.item_app_list, null); ImageView iv = convertView.findViewById(R.id.app_icon_iv); TextView tv = convertView.findViewById(R.id.app_name_tv); tv.setText(appNameList.get(position)); return convertView; } } }

点击事件与长按事件

java
public class AppListActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_list); ListView listView = findViewById(R.id.app_lv); appNameList = Arrays.asList("QQ", "微信", "慕课网", "牛客"); List<ResolveInfo> resolveInfoList = getAppInfo(); listView.setAdapter(new AppListAdapter(resolveInfoList)); // 点击事件写法二 listView.setOnItemClickListener((parent, view, position, id) -> { ResolveInfo resolveInfo = resolveInfoList.get(position); String packageName = resolveInfo.activityInfo.packageName; String className = resolveInfo.activityInfo.name; ComponentName componentName = new ComponentName(packageName, className); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent); }); // 长按的事件 listView.setOnItemLongClickListener((parent, view, position, id) -> { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); builder.setMessage("确定删除吗?"); builder.setPositiveButton("确定", (dialog, which) -> { // 移除此条目 resolveInfoList.remove(position); listView.setAdapter(new AppListAdapter(resolveInfoList)); }); builder.setNegativeButton("取消", null); builder.show(); return false; }); } // 获取所有的应用信息 private List<ResolveInfo> getAppInfo(){ Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); return getPackageManager().queryIntentActivities(intent, 0); } public class AppListAdapter extends BaseAdapter { private List<ResolveInfo> resolveInfoList; public AppListAdapter(List<ResolveInfo> appInfo) { this.resolveInfoList = appInfo; } @Override public int getCount() { return resolveInfoList.size(); } @Override public Object getItem(int position) { return resolveInfoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.item_app_list, null); ImageView iv = convertView.findViewById(R.id.app_icon_iv); TextView tv = convertView.findViewById(R.id.app_name_tv); ResolveInfo resolveInfo = resolveInfoList.get(position); tv.setText(resolveInfo.activityInfo.loadLabel(getPackageManager())); iv.setImageDrawable(resolveInfo.activityInfo.loadIcon(getPackageManager())); // 点击事件写法一 convertView.setOnClickListener((v) -> { String packageName = resolveInfo.activityInfo.packageName; String className = resolveInfo.activityInfo.name; ComponentName componentName = new ComponentName(packageName, className); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent); }); return convertView; } } }

设置HeaderView与FooterView

header_app_list.xml

xml
<?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="vertical"> <TextView android:gravity="center" android:textSize="20sp" android:text="This is listView's header." android:id="@+id/header_app_list_iv" android:background="@color/colorAccent" android:layout_width="match_parent" android:layout_height="80dp"/> </LinearLayout>

AppListActivity.java(其实只需要在setAdapter之前做一个addHeaderView的操作即可)

java
public class AppListActivity extends AppCompatActivity { private List<String> appNameList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_list); ListView listView = findViewById(R.id.app_lv); appNameList = Arrays.asList("QQ", "微信", "慕课网", "牛客", "招商银行"); // 增加头Header listView.addHeaderView(getLayoutInflater().inflate(R.layout.header_app_list, null)); List<ResolveInfo> resolveInfoList = getAppInfo(); listView.setAdapter(new AppListAdapter(resolveInfoList)); // 点击事件写法二 listView.setOnItemClickListener((parent, view, position, id) -> { ResolveInfo resolveInfo = resolveInfoList.get(position); String packageName = resolveInfo.activityInfo.packageName; String className = resolveInfo.activityInfo.name; ComponentName componentName = new ComponentName(packageName, className); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent); }); // 长按的事件 listView.setOnItemLongClickListener((parent, view, position, id) -> { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); builder.setMessage("确定删除吗?"); builder.setPositiveButton("确定", (dialog, which) -> { resolveInfoList.remove(position); listView.setAdapter(new AppListAdapter(resolveInfoList)); }); builder.setNegativeButton("取消", null); builder.show(); return false; }); } // 获取所有的应用信息 private List<ResolveInfo> getAppInfo(){ Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); return getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_ALL); } public class AppListAdapter extends BaseAdapter { private List<ResolveInfo> resolveInfoList; public AppListAdapter(List<ResolveInfo> appInfo) { this.resolveInfoList = appInfo; } @Override public int getCount() { return resolveInfoList.size(); } @Override public Object getItem(int position) { return resolveInfoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.item_app_list, null); ImageView iv = convertView.findViewById(R.id.app_icon_iv); TextView tv = convertView.findViewById(R.id.app_name_tv); ResolveInfo resolveInfo = resolveInfoList.get(position); tv.setText(resolveInfo.activityInfo.loadLabel(getPackageManager())); iv.setImageDrawable(resolveInfo.activityInfo.loadIcon(getPackageManager())); return convertView; } } }

ListView的优化

真正意义上的优化: http://www.xuanyusong.com/archives/1252

java
public class AppListActivity extends AppCompatActivity { private List<String> appNameList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_list); ListView listView = findViewById(R.id.app_lv); appNameList = Arrays.asList("QQ", "微信", "慕课网", "牛客", "招商银行", "支付宝"); // 增加头Header listView.addHeaderView(getLayoutInflater().inflate(R.layout.header_app_list, null)); List<ResolveInfo> resolveInfoList = getAppInfo(); listView.setAdapter(new AppListAdapter(resolveInfoList)); } // 获取所有的应用信息 private List<ResolveInfo> getAppInfo(){ Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); return getPackageManager().queryIntentActivities(intent, 0); } public class AppListAdapter extends BaseAdapter { private List<ResolveInfo> resolveInfoList; public AppListAdapter(List<ResolveInfo> appInfo) { this.resolveInfoList = appInfo; } @Override public int getCount() { return resolveInfoList.size(); } @Override public Object getItem(int position) { return resolveInfoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if(convertView == null){ LayoutInflater layoutInflater = getLayoutInflater(); convertView = layoutInflater.inflate(R.layout.item_app_list, null); viewHolder = new ViewHolder(); viewHolder.imageView = convertView.findViewById(R.id.app_icon_iv); viewHolder.textView = convertView.findViewById(R.id.app_name_tv); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } ResolveInfo resolveInfo = resolveInfoList.get(position); viewHolder.textView.setText(resolveInfo.activityInfo.loadLabel(getPackageManager())); viewHolder.imageView.setImageDrawable(resolveInfo.activityInfo.loadIcon(getPackageManager())); return convertView; } } // ViewHolder private static class ViewHolder { public ImageView imageView; public TextView textView; } }

条目布局分类加载

item_left_chat.xml

xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/time_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="21:52" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" tools:ignore="MissingConstraints" /> <ImageView android:id="@+id/icon_iv" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/time_tv" tools:ignore="MissingConstraints" /> <TextView android:id="@+id/name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tim" app:layout_constraintEnd_toEndOf="@+id/icon_iv" app:layout_constraintStart_toStartOf="@+id/icon_iv" app:layout_constraintTop_toBottomOf="@+id/icon_iv" /> <TextView android:id="@+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, how are you?" android:paddingStart="10sp" app:layout_constraintBottom_toBottomOf="@+id/icon_iv" app:layout_constraintStart_toEndOf="@+id/icon_iv" app:layout_constraintTop_toTopOf="@+id/icon_iv" tools:ignore="MissingConstraints" /> </androidx.constraintlayout.widget.ConstraintLayout>

item_right_chat.xml

xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/time_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="21:52" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" tools:ignore="MissingConstraints" /> <TextView android:id="@+id/name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tim" app:layout_constraintEnd_toEndOf="@+id/icon_iv" app:layout_constraintStart_toStartOf="@+id/icon_iv" app:layout_constraintTop_toBottomOf="@+id/icon_iv" /> <TextView android:id="@+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, how are you?" android:paddingEnd="10sp" app:layout_constraintBottom_toBottomOf="@+id/icon_iv" app:layout_constraintEnd_toStartOf="@+id/icon_iv" app:layout_constraintTop_toTopOf="@+id/icon_iv" tools:ignore="MissingConstraints" /> <ImageView android:id="@+id/icon_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/time_tv" tools:ignore="MissingConstraints" /> </androidx.constraintlayout.widget.ConstraintLayout>

现在拥有item_left_chat.xml和item_right_chat.xml两个布局,所以只需要做好分类布局加载就好了:

java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.main_lv); List<ChatMessage> chatMessages = Arrays.asList( new ChatMessage(1, 2, "Tim", "08:20", "I'm Tim.", true), new ChatMessage(1, 2, "Tim", "08:25", "Jone, how are you?", true), new ChatMessage(2, 1, "Jone", "08:30", "I'm fine, thinks", false), new ChatMessage(1, 2, "Tim", "08:31", "No thinks.", true), new ChatMessage(2, 1, "Jone", "08:32", "What can I do for you ?", false), new ChatMessage(1, 2, "Tim", "08:59", "Please give me some money.", true) ); listView.setAdapter(new ChatMessageAdapter(chatMessages, MainActivity.this)); } static class ChatMessage { public int mId; public int mFriendId; public String mName; public String mDate; public String mContent; public boolean mIsComeMessage; public ChatMessage(int mId, int mFriendId, String mName, String mDate, String mContent, boolean mIsComeMessage) { this.mId = mId; this.mFriendId = mFriendId; this.mName = mName; this.mDate = mDate; this.mContent = mContent; this.mIsComeMessage = mIsComeMessage; } } static class ChatMessageAdapter extends BaseAdapter { List<ChatMessage> chatMessages; Context context; interface IMessageViewType { int COM_MESSAGE = 1; int TO_MESSAGE = 2; } public ChatMessageAdapter(List<ChatMessage> chatMessages, Context context) { this.chatMessages = chatMessages; this.context = context; } @Override public int getCount() { return chatMessages.size(); } @Override public Object getItem(int position) { return chatMessages.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); ChatMessage chatMessage = chatMessages.get(position); if(convertView == null){ if(chatMessage.mIsComeMessage){ convertView = layoutInflater.inflate(R.layout.item_left_chat, null); }else{ convertView = layoutInflater.inflate(R.layout.item_right_chat, null); } TextView timeTv = convertView.findViewById(R.id.time_tv); ImageView iconIv = convertView.findViewById(R.id.icon_iv); TextView nameTv = convertView.findViewById(R.id.name_tv); TextView contentTv = convertView.findViewById(R.id.content_tv); timeTv.setText(chatMessage.mDate); nameTv.setText(chatMessage.mName); contentTv.setText(chatMessage.mContent); } return convertView; } @Override public int getItemViewType(int position) { ChatMessage chatMessage = chatMessages.get(position); return chatMessage.mIsComeMessage ? IMessageViewType.COM_MESSAGE : IMessageViewType.TO_MESSAGE; } @Override public int getViewTypeCount() { return 2; // IMessageViewType 两种类型 } } }

CardView

CardView是用于实现卡片式布局效果的重要控件,实际上也是一个FrameLayout,只是额外提供了圆角和阴影,看上去有立体效果。

CardView是什么?

  1. Android5.0之后新增
  2. com.android.support:cardview-v7:26.1.0独立引入
  3. 继承自FrameLayout,方便作为其他控件容器,添加3D阴影和圆角效果

CardView常用属性

  1. cardBackgroundColor设置背景色
  2. cardCornerRadius设置圆角半径
  3. contentPadding 设置内部padding
  4. cardElevation设置阴影大小
  5. cardUseCompatPadding 默认为false,用于5.0及以上,true则添加额外的padding绘制阴影
  6. cardPreventCornerOverlap 默认为true,用于5.0以下,添加额外的padding,防止内容和圆角重叠

CardView的常用属性

引入CardView的依赖

groovy
implementation 'androidx.cardview:cardview:1.0.0'

一个VardView的小Demo:

xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".MainActivity"> <!-- cardBackgroundColor:设置背景色 cardCornerRadius:设置圆角 cardElevation:设置阴影 contentPadding:设置内部padding --> <androidx.cardview.widget.CardView android:layout_gravity="center" app:cardBackgroundColor="@color/colorAccent" app:cardCornerRadius="10dp" app:cardElevation="5dp" app:contentPadding="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="200dp" android:layout_height="50dp" android:text="Hello World!" android:gravity="center" android:layout_gravity="center" /> </androidx.cardview.widget.CardView> </FrameLayout>

其实可以看到CardView还真的是有种卡片效果的。常用的属性如下:

属性作用
card_view
阴影的大小
card_view
阴影最大高度
card_view
卡片的背景色
card_view
卡片的圆角大小
card_view
卡片内容于边距的间隔
card_view
卡片内容与底部的边距
card_view
卡片内容与顶部的边距
card_view
卡片内容与左边的边距
card_view
卡片内容与右边的边距
card_view
卡片内容于边距的间隔起始
card_view
卡片内容于边距的间隔终止
card_view
设置内边距,V21+的版本和之前的版本仍旧具有一样的计算方式
card_view
在V20和之前的版本中添加内边距,这个属性为了防止内容和边角的重叠

CardView使用示例

先把展示的图片发放在drawable下的xxhdpi下:分别是img01-img05。

item_msg.xml ,这是ListView的条目布局:

xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"> <androidx.cardview.widget.CardView app:cardCornerRadius="8dp" app:cardElevation="5dp" app:cardUseCompatPadding="false" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/item_icon_iv" android:scaleType="centerCrop" tools:src="@drawable/img01" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/item_title_tv" android:layout_margin="8dp" android:textColor="#000000" android:textSize="16sp" android:textStyle="bold" tools:text="一起来学习Android技术" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/item_content_tv" android:layout_margin="8dp" android:textColor="#000000" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="8dp" tools:text="一起来学习Android技术, 一起来学习Android技术。" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </androidx.cardview.widget.CardView> </FrameLayout>

main_activity.xml

xml
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/id_listview_msg_list" android:divider="@null" android:background="#ffffff" android:paddingTop="8dp" tools:context=".MainActivity"> </ListView>

MainActivity.java

java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setTitle("CardView测试"); setContentView(R.layout.activity_main); ListView msgListView = findViewById(R.id.id_listview_msg_list); List<Msg> messageList = Arrays.asList( new Msg(1, R.drawable.img01, "如何才能不错过人工智能的时代?", "下一个时代就是机器学习的时代,与你一起预见未来!"), new Msg(2, R.drawable.img02, "关于你的面试、实习心路历程", "奖品丰富,更设有参与奖,随机抽取5名幸运用户,获得付费面试课程中的任意一门!"), new Msg(3, R.drawable.img03, "狗粮不是你想吃,就能吃的!", "你的朋友圈开始了吗?一半秀恩爱,一半扮感伤!不怕,陪你坚强地走下去!"), new Msg(4, R.drawable.img04, "前端跳槽面试那些事儿~", "工作有几年了,项目偏简单有点拿不出手怎么办?目前还没毕业,正在自学前端,请问可以找到一份前端工作吗,我该怎么办?"), new Msg(5, R.drawable.img05, "图解程序员怎么过七夕?", "图解程序员怎么过七夕,哈哈哈哈,活该单身25年!") ); msgListView.setAdapter(new MoocAdapter(messageList)); } class MoocAdapter extends BaseAdapter { private List<Msg> msgList; public MoocAdapter(List<Msg> msgList) { this.msgList = msgList; } @Override public int getCount() { return msgList.size(); } @Override public Object getItem(int position) { return msgList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if(convertView == null){ convertView = View.inflate(MainActivity.this, R.layout.item_msg, null); //convertView = getLayoutInflater().inflate(R.layout.item_msg, null); viewHolder = new ViewHolder(); viewHolder.iconImageView = convertView.findViewById(R.id.item_icon_iv); viewHolder.titleTextView = convertView.findViewById(R.id.item_title_tv); viewHolder.contentTextView = convertView.findViewById(R.id.item_content_tv); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } Msg msg = msgList.get(position); viewHolder.contentTextView.setText(msg.getContent()); viewHolder.titleTextView.setText(msg.getTitle()); viewHolder.iconImageView.setImageResource(msg.getImgResId()); return convertView; } } static class ViewHolder { ImageView iconImageView; TextView titleTextView; TextView contentTextView; } } @Data @AllArgsConstructor @NoArgsConstructor class Msg { private int id; private int imgResId; private String title; private String content; }

看看最终的展示效果:

这里用到了lombok这款插件,那就顺便说一下lombok在Android开发中如何使用吧。

使用tools工具预览

xml
<!-- 引入tools命令空间 --> xmlns:tools="http://schemas.android.com/tools" <TextView android:id="@+id/item_title_tv" android:layout_margin="8dp" android:textColor="#000000" android:textSize="16sp" android:textStyle="bold" tools:text="一起来学习Android技术" android:layout_width="match_parent" android:layout_height="wrap_content"/>

使用tools工具可以进行控件效果预览,如果直接写了android

=XXX,那么很可能在数据无法正确加载的情况下显示出我们定义的android
属性,所以无论是ImageView还是TextView等需要添加数据才可以预览的情况都可以使用tools这个命名空间。

Lombok在Android中的使用

引入lombok的依赖:

groovy
// 这是CardView的依赖 implementation 'androidx.cardview:cardview:1.0.0' // 配置Lombok注解处理器 annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.12' // 声明lombok的依赖作用域 compileOnly(group: 'org.projectlombok', name: 'lombok', version: '1.18.12')

安装Lombok的插件:

安装好插件后重启AndroidStudio即可使用Lombok插件。

最后别忘了在moudle或者project底下新建一个lombok.config:

ini
lombok.anyConstructor.suppressConstructorProperties=true

然后开始愉快的写代码吧 ~

编译时编码错误解决方案

groovy
android { compileSdkVersion ... buildToolsVersion "..." // 指定编码为UTF-8 compileOptions { encoding "UTF-8" } ... }

Android屏幕适配

这个专门放置一篇博客!

本文作者:Tim

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!