Android开发——RecycleView设计及activity生命周期及界面跳转
RecycleView设计
概念
RecycleView是Android5.0推出的,它用来代替ListView和GridView,并且能够实现瀑布流中的布局,更加高级并且更加灵活,提供更为高效的回收复用机制,同时实现管理和视图的解耦合。
项目功能简介
- 完成联系人界面的目录展示,并且实现吸顶布局效果展现
具体步骤及关键代码
- 联系人界面包括头像和联系人昵称两项数据,因此设计一个WeChatContactsItem类,其中sticky表示该item数据所属的组。
public class WeChatContactsItem {
public String sticky;
public ImageView imageView;
public String dataWechatContactsName;
}
- 联系人界面的item布局需为水平方向上的LinearLayout,左边放imageview,右边放textview,同时在item上方应有include语句,引入吸顶布局item。
<include layout="@layout/layout_sticky_header_view" />
<LinearLayout
android:id="@+id/LinearLayoutWechatContactsItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5sp"
android:layout_weight="1"
android:background="#F40"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/wechat_contacts_name_image"
android:layout_width="wrap_content"
android:layout_height="60sp"
android:layout_weight="1"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/wechat_contacts_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="微信联系人名字"
android:textSize="16sp" />
</LinearLayout>
- 吸顶文本用来实现吸顶布局的显示
<TextView
android:id="@+id/tv_sticky_header_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/design_default_color_primary"
android:gravity="center"
android:padding="10dp"
android:text="吸顶文本"
android:textColor="@android:color/white"
android:textSize="14sp" />
- 通过contacts主函数进行数据的上传,同时修改adapter继承RecycleView.Adapter,来完成item的初始化。
for(int i=0;i<10;i++){
WeChatContactsItem weChatContactsItem = new WeChatContactsItem();
weChatContactsItem.sticky = "这是0-10的顶部";
weChatContactsItem.dataWechatContactsName = "这是第"+i+"个微信联系人名字";
dataWechatContactsItems.add(weChatContactsItem);
}
for(int i=10;i<20;i++){
WeChatContactsItem weChatContactsItem = new WeChatContactsItem();
weChatContactsItem.sticky = "这是10-20的顶部";
weChatContactsItem.dataWechatContactsName = "这是第"+i+"个微信联系人名字";
dataWechatContactsItems.add(weChatContactsItem);
}
for(int i=10;i<30;i++){
WeChatContactsItem weChatContactsItem = new WeChatContactsItem();
weChatContactsItem.sticky = "这是20-30的顶部";
weChatContactsItem.dataWechatContactsName = "这是第"+i+"个微信联系人名字";
dataWechatContactsItems.add(weChatContactsItem);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, @SuppressLint("RecyclerView") int position) {
WeChatContactsItem wechatContactsItem = dataWechatContactsItems.get(position);
holder.wechat_contacts_name_image.setImageDrawable(context.getDrawable(R.drawable.contacts));
holder.wechat_contacts_name.setText(wechatContactsItem.dataWechatContactsName);
- 以下代码用来判断是否是第一个头部以及有无头部,并进行相应的操作
public static final int FIRST_STICKY_VIEW = 1;
public static final int HAS_STICKY_VIEW = 2;
public static final int NONE_STICKY_VIEW = 3;
- 以下代码用来对上面三种情况进行判别,position=0即第一个item,此时吸顶文字应展示,且标记为FIRST_STICKY_VIEW;之后的item都会和前一个item要展示的吸顶信息进行比较,不相同就展示,并且标记tag为HAS_STICKY_VIEW;相同就不展示,并且标记tag为NONE_STICKY_VIEW
//吸顶布局具体实现代码
// System.out.println(!TextUtils.equals(wechatItem.sticky, dataWechatItems.get(position - 1).sticky));
if (position == 0) {// 第一个item的吸顶信息肯定是展示的,并且标记tag为FIRST_STICKY_VIEW
holder.linearLayoutWechatContactsItem.setBackgroundColor(Color.rgb(255,255,0));
holder.tvStickyHeader.setVisibility(View.VISIBLE);
holder.tvStickyHeader.setText(wechatContactsItem.sticky);
holder.itemView.setTag(FIRST_STICKY_VIEW);
} else { // 之后的item都会和前一个item要展示的吸顶信息进行比较,不相同就展示,并且标记tag为HAS_STICKY_VIEW
if (!TextUtils.equals(wechatContactsItem.sticky, dataWechatContactsItems.get(position - 1).sticky)) {
System.out.println(position);
holder.linearLayoutWechatContactsItem.setBackgroundColor(Color.rgb(255,0,0));
holder.tvStickyHeader.setVisibility(View.VISIBLE);
holder.tvStickyHeader.setText(wechatContactsItem.sticky);
holder.itemView.setTag(HAS_STICKY_VIEW);
} else { // 相同就不展示,并且标记tag为NONE_STICKY_VIEW
holder.linearLayoutWechatContactsItem.setBackgroundColor(Color.rgb(0,255,0));
holder.tvStickyHeader.setVisibility(View.GONE);
holder.itemView.setTag(NONE_STICKY_VIEW);
}
}
// ContentDescription 用来记录并获取要吸顶展示的信息
holder.itemView.setContentDescription(wechatContactsItem.sticky);
- 修改contacts main文件,增加滑动监听事件
//添加鼠标滚动事件,以此来实现吸顶布局效果
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//找到RecyclerView的item中,和RecyclerView的getTop 向下相距5个像素的那个item
View stickyInfoView = recyclerView.findChildViewUnder(
tvStickyHeaderView.getMeasuredWidth() / 2, 5);
//如果该item不为空,则将它的值赋值给HeaderView进行显示
if (stickyInfoView != null && stickyInfoView.getContentDescription() != null) {
tvStickyHeaderView.setText(String.valueOf(stickyInfoView.getContentDescription()));
}
//先将吸顶文字展示出来才能使用getMeasuredHeight计算器高度
int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
tvStickyHeaderView.measure(w, h);
View transInfoView = recyclerView.findChildViewUnder(
tvStickyHeaderView.getMeasuredWidth() / 2, tvStickyHeaderView.getMeasuredHeight() + 1);
// 找到固定在屏幕上方那个FakeStickyLayout下面一个像素位置的RecyclerView的item,
// 我们根据这个item来更新假的StickyLayout要translate多少距离.
// 并且只处理HAS_STICKY_VIEW和NONE_STICKY_VIEW这两种tag,
// 因为第一个item的StickyLayout虽然展示,但是一定不会引起FakeStickyLayout的滚动.
if (transInfoView != null && transInfoView.getTag() != null) {
int transViewStatus = (int) transInfoView.getTag();
int dealtY = transInfoView.getTop() - tvStickyHeaderView.getMeasuredHeight();
if (transViewStatus == MyadapterContacts.HAS_STICKY_VIEW) {
if (transInfoView.getTop() > 0) {
tvStickyHeaderView.setTranslationY(dealtY);
} else {
tvStickyHeaderView.setTranslationY(0);
}
} else if (transViewStatus == MyadapterContacts.NONE_STICKY_VIEW) {
tvStickyHeaderView.setTranslationY(0);
}
}
}
});
效果展示
RecyclerView使用方法总结:https://www.jianshu.com/p/c4cfe38a91ed
activity生命周期
activity概念
Activity称为活动组件(也称界面程序),它会加载布局文件(属于资源文件),如setContentView(R.layout.activity_main)。作为Android四大组件之一的Activity组件,都会在清单文件里注册。
在AS环境中,开发Activity所使用的基类是AppCompatActivity
生命周期概念
Activity生命周期指Activity从创建到销毁的过程。Activity表现为四种状态:
- 活动状态Active: Activity在用户界面中处于最上层,完全能被用户看到,能够与用户进行交互。
- 暂停状态Pause: Activity在界面上被部分遮挡,不再处于用户界面的最上层,且不能够与用户进行交互。(如弹出消息框)
- 停止状态Stop: Activity被其他Activity全部遮挡,界面完全不能被用户看到。(如玩游戏时来电了)
- 非活动状态Dead: Activity没有启动或者被finish()。
界面跳转功能实现
思路分析
界面跳转即从一个activity跳转到另一个activity,下面笔者将以从联系人目录界面跳转至联系人详情界面进行讲解:
首先要创建新的detail activity,然后在contacts 的adapter中设置监听事件,通过鼠标单击,命令程序跳转至另一个activity,同时传入相关的数据,来填充联系人详情界面。
具体步骤及关键代码
- 创建ContactsDetails
2.在adapter中设置监听事件,并传入数据
holder.linearLayoutWechatContactsItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.linearLayoutWechatContactsItem.setBackgroundColor(Color.rgb(255,255,0));
Intent intent = new Intent(context,ContactsDetails.class);
intent.putExtra("name", holder.wechat_contacts_name.getText().toString());
context.startActivity(intent);
}
});
- 在ContactsDetails中接受intent及其数据,并将数据展示出来
private TextView wechat_contacts_details;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts_details);
Log.d("life","activity_contacts_details is creating...");
Intent intent = getIntent();
String name = intent.getStringExtra("name");
Log.d("life","name:"+name);
wechat_contacts_details = findViewById(R.id.wechat_contacts_details);
wechat_contacts_details.setText(name+"的详情界面");
}