文章目录
- 一、引言
- 二、设计
- 1、下拉刷新
- (1)依赖
- (2)使用
- 2、图片需求
- 三、结论
一、引言
- 描述:设计一个简单说说功能模块
- 需求:
1、能够下拉刷新,更新数据
2、一条说说里允许包含多张图片,图片能够放大查看 - 难度:初级
- 知识点:
1、Swiperefreshlayout
2、适配器Adapter
3、对话框Dialog
4、文字图标Icon
二、设计
1、下拉刷新
- 思路
使用官方提供的解决方案SwipeRefreshLayout,具有简单、灵活的特点。不足之处是无法刷新头部和加载更多的功能。
(1)依赖
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03'
(2)使用
- 效果图
- UI界面
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 需要刷新的界面 -->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout/>
- 后台
/**
* @title:下拉刷新
* @param activity
*/
private void getSwipeRefreshLayout(final View activity) {
final SwipeRefreshLayout swipeRefreshLayout = activity.findViewById(R.id.swipe);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Thread(new Runnable() {
@Override
public void run() {
try {
//设置刷新时长为1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//更新数据
Log.i("Home","刷新数据");
// 数据更新方法
swipeRefreshLayout.setRefreshing(false);
}
});
}
}).start();
}
});
}
2、图片需求
- 思路
多张图片:内容适配器嵌套图片适配器
图片放大:使用对话框,将获取的图片数据放入对话框内展示
- 效果图
- UI界面
(内容适配器)
<?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"
android:padding="@dimen/hPadding"
android:background="@drawable/shape"
android:orientation="vertical"
android:layout_marginBottom="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/userImage"
android:layout_width="@dimen/huImage"
android:layout_height="@dimen/huImage"
android:layout_margin="@dimen/huImageMargin"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/huName"/>
<TextView
android:id="@+id/sayTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/hTime"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/hTextHeight"
android:orientation="vertical"
android:layout_marginLeft="@dimen/huImageMargin">
<TextView
android:id="@+id/sayText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/hTimeTop"
android:textSize="@dimen/hName"
android:textColor="@color/comm_hText"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/sayImages"
android:layout_width="match_parent"
android:layout_height="@dimen/hImage"
android:layout_marginTop="@dimen/hTimeTop" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_marginTop="3dp"
android:layout_marginRight="6dp"
android:layout_width="@dimen/position"
android:layout_height="@dimen/position"
android:src="@drawable/position"/>
<TextView
android:id="@+id/sayPosition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/comm_hText"
android:layout_marginRight="@dimen/positionRight"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/hTimeTop"
android:layout_marginLeft="@dimen/huImageMargin">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="评论区"
android:textSize="13dp"/>
</LinearLayout>
</LinearLayout>
(图片适配器)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_image"
android:layout_width="@dimen/hImage"
android:layout_height="@dimen/hImage" />
</LinearLayout>
- 后台
(实体)
public class Say {
Long id;
int status;
Long userId;
String text;
String images;
String time;
String newTime;
String position;
// 其他
String name;
String image;
public Long getId() {
return id;
}
public int getStatus() {
return status;
}
public Long getUserId() {
return userId;
}
public String getText() {
return text;
}
public String getImages() {
return images;
}
public String getTime() {
return time;
}
public String getNewTime() {
return newTime;
}
public String getPosition() {
return position;
}
public String getName() {
return name;
}
public String getImage() {
return image;
}
public void setId(Long id) {
this.id = id;
}
public void setStatus(int status) {
this.status = status;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public void setText(String text) {
this.text = text;
}
public void setImages(String images) {
this.images = images;
}
public void setTime(String time) {
this.time = time;
}
public void setNewTime(String newTime) {
this.newTime = newTime;
}
public void setPosition(String position) {
this.position = position;
}
public void setName(String name) {
this.name = name;
}
public void setImage(String image) {
this.image = image;
}
@Override
public String toString() {
return "Say{" +
"id=" + id +
", status=" + status +
", userId=" + userId +
", text='" + text + '\'' +
", images='" + images + '\'' +
", time='" + time + '\'' +
", newTime='" + newTime + '\'' +
", position='" + position + '\'' +
", name='" + name + '\'' +
", image='" + image + '\'' +
'}';
}
}
(内容适配器)
public class SayAdapter extends RecyclerView.Adapter<SayAdapter.ViewHolder>{
private List<Say> sayList; // 定义容器
// private int say_admin; // 读取类型
BitmapDrawable bitmapDrawable;
private Handler handler = null;
public SayAdapter(List<Say> listSay) {
this.sayList = listSay;
}
// 绑定控件
static class ViewHolder extends RecyclerView.ViewHolder {
View sayView;
ImageView userImage;
TextView userName,sayTime,sayText,sayPosition;
RecyclerView recyclerView;
public ViewHolder(View itemView) {
super(itemView);
sayView = itemView;
userImage = itemView.findViewById(R.id.userImage);
userName = itemView.findViewById(R.id.userName);
sayTime = itemView.findViewById(R.id.sayTime);
sayText = itemView.findViewById(R.id.sayText);
sayPosition = itemView.findViewById(R.id.sayPosition);
recyclerView = itemView.findViewById(R.id.sayImages);
}
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
//加载适配器布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.say,parent,false);
//循环加载适配器布局,从而达到减少资源使用
final SayAdapter.ViewHolder holder = new SayAdapter.ViewHolder(view);
// 模块点击点击事件
holder.sayView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(parent.getContext(),sayList.get(viewType).getText(),Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull final SayAdapter.ViewHolder holder, int position) {
final Say s = sayList.get(position);
holder.userName.setText(s.getName());
holder.sayTime.setText((CharSequence) s.getTime());
holder.sayText.setText(s.getText());
holder.sayPosition.setText(s.getPosition());
// userImage
//用户名头像
showUserImage(holder,s.getImage());
// sayImages
// 说说多图片显示
showSayImage(holder,s.getImages());
}
/**
* Returns the total number of items in the data set held by the adapter.
*
* @return The total number of items in this adapter.
*/
@Override
public int getItemCount() {
return sayList.size();
}
/**
* @title:头像显示
* @param holder
* @param url
*/
private void showUserImage(final SayAdapter.ViewHolder holder, final String url){
handler = new Handler();
final Runnable runnable = new Runnable() {
@Override
public void run() {
holder.userImage.setImageDrawable(bitmapDrawable);
}
};
new Thread(new Runnable() {
@Override
public void run() {
try {
bitmapDrawable = okHttp.getBitmap(Api.userImage,url);
handler.post(runnable);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* @title:说说图片显示
* @param holder
* @param say_images
*/
private void showSayImage(ViewHolder holder, String say_images) {
// 解析符合图片资源
String[] sayImages = say_images.split("\\|");
List<String> sayI = new ArrayList<>();
Collections.addAll(sayI,sayImages);
//1.获取RecyclerView控件信息
//2.RecyclerView控件的使用方法
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
//3.横向滑动
holder.recyclerView.setLayoutManager(layoutManager);
//4.数据载入适配器,数据填充
ImageAdapter adapter = new ImageAdapter(sayI);
holder.recyclerView.setAdapter(adapter);
}
}
(图片适配器)
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
//定义一个list容器
private List<String> listString;
BitmapDrawable bitmapDrawable;
private Handler handler = null;
//绑定android界面控件
static class ViewHolder extends RecyclerView.ViewHolder {
View ImageView;
ImageView hImage;
public ViewHolder(View itemView) {
super(itemView);
ImageView = itemView;
hImage = itemView.findViewById(R.id.item_image);
}
}
public ImageAdapter(List<String> list){
listString = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
//加载适配器布局
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image,viewGroup,false);
//循环加载适配器布局,从而达到减少资源使用
final ViewHolder holder = new ViewHolder(view);
//图片放大
ImageFD(holder);
return holder;
}
/** 图片放大与关闭 **/
private void ImageFD(final ViewHolder holder) {
//再次点击进行关闭
holder.hImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取对应的图片对象
ImageView imgView = new ImageView(holder.hImage.getContext());
imgView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imgView.setImageDrawable(bitmapDrawable);
//思路是:使用对话框,将获取的图片数据放入对话框内展示
final Dialog dialog = new Dialog(holder.ImageView.getContext(),android.R.style.Theme_Black_NoTitleBar_Fullscreen);
dialog.setContentView(imgView);
dialog.show();
//再次点击进行关闭
imgView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
});
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, int i) {
//将数据依次与适配器匹配
final String s = listString.get(i);
handler = new Handler();
final Runnable runnable = new Runnable() {
@Override
public void run() {
viewHolder.hImage.setImageDrawable(bitmapDrawable);
}
};
new Thread(new Runnable() {
@Override
public void run() {
try {
bitmapDrawable = okHttp.getBitmap(Api.sayImage,s);
handler.post(runnable);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public int getItemCount() {
return listString.size();
}
}
三、结论
正常的说说模块,按道理应该还需要点赞、收藏、分享、屏蔽等一些功能,这里我就不一一设计了。思路其实很简单:
点赞:使用Redis收集点赞用户信息,每隔三十分钟使用Spring Task归档一次或者晚上人流量少时定点统一归档。
收藏:独立设计一张表,主字段:当前用户id、说说id,app本地再设计一张表用于缓存,剩下的就是IDUS。
分享:定义一个特定的链接,比如:https://www.xpq.com/abcdef其中www.xpq.com为网址,abcdef为说说识别字段。如果还需要设置分享时间,比如:https://www.xpq.com/20230609/30/abcdef。20230609为开始时间,30表示一个月的过期时间。
屏蔽:本地数据库获取到的说说信息里添加一个state字段,用于界面显示的一个“撞针”。