本次Github代码仓库 --crcr1013/MyWechat
一、成果要求
1、在发现界面实现新的RecyclerView布局,包括"朋友圈"、"听一听"内容。
2、对于"朋友圈"item,点击其可跳转到其详情界面,详情界面设计同样利用RecyclerView纵向布局,包括头像,昵称,朋友圈文案,配图等内容;对于"听一听"item,点击其可跳转到其详情界面,详情界面是一个类音乐播放器界面,本次实验暂不添加播放音乐,下一首,进度条等具体功能,仅仅进行一个界面展示。以上两个跳转利用Intent启动Activity来实现。
二、关键步骤
1、准备工作
1.1环境准备
我当前的微信APP设计成果为,第一个tab页–聊天界面实现了对RecyclerView的纵向布局,展示find.xml的格式内容,对item添加点击事件,实现Item的上下拖拽及左滑删除,但本次实验我计划在tab3(发现界面)上进行。
1.2布局构想及资源准备
本次实验我计划在tab3(发现界面)利用RecyclerView布局添加两个"朋友圈","听一听"两个Item,再进行点击时分别跳转启动FcircleActivity以及ListenActivity。
FcircleActivity对应的布局文件为activity_fcircle.xml,其又利用RecyclerView布局展示fcircle.xml的格式内容;ListenActivity对应的布局文件为listen.xml,直接进行简单的界面展示,日后可将其丰富为真正的音乐播放器。
本次发现界面的RecyclerView布局计划初始化两个item,“朋友圈"和"听一听”,对应布局文件find.xml设计构想如下,故需准备两个标识图标(以及一个右箭头图标)。
朋友圈RecyclerView布局计划初始化两个item,对应布局文件fcircle.xml设计构想如下,需准备至少两张头像图片,两张配图图片(以及一个点赞图标)。
listen.xml设计构想如下,需准备一张音乐海报图片。
2、 朋友圈的RecyclerView布局
2.1 activity_fcircle.xml
由于在朋友圈界面也利用RecyclerView进行布局,故添加一个RecyclerView,并设置其id,以便后面使用。另外添加一个title,recycleview则要包括在FrameLayout中。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
tools:context=".FcircleActivity">
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="76dp"
android:layout_weight="1"
android:background="#ccccff"
android:gravity="center"
android:text="朋友圈"
android:textColor="@color/white"
android:textSize="30sp"
tools:ignore="TextContrastCheck" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/RecyclerView_fcircle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
2.2 fcircle.xml
新建一个find.xml,为朋友圈的RecyclerView内的元素设定xml样式。
放入一个水平向的linearLayout,添加一个放头像的ImageView,再放入一个竖直向的LinearLayout,在这个Layout里面放入一个放昵称的TextView,一个放配图的ImageView,一个水平向的LinearLayout,在这个水平向的LinearLayout中放入一个放点赞图标的ImageView,一个放点赞人的TextView;再根据具体情况调整文字大小,整个LinearLayout的width、height等,注意设置头像,文本,昵称,配图的id,方便之后进行初始化。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="horizontal"
tools:context=".FcircleActivity">
<ImageView
android:id="@+id/imageView_touxiang"
android:layout_width="135dp"
android:layout_height="95dp"
android:layout_gravity="left"
android:layout_weight="0"
tools:srcCompat="@drawable/photo_p1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="vertical">
<TextView
android:id="@+id/textView_name"
android:layout_width="wrap_content"
android:layout_height="57dp"
android:layout_weight="0"
android:gravity="left"
android:text="小马"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView_wenben"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="哈哈哈哈哈哈哈哈哈"
android:textSize="30sp" />
<ImageView
android:id="@+id/imageView_picture"
android:layout_width="match_parent"
android:layout_height="265dp"
android:layout_weight="0"
tools:srcCompat="@drawable/songimage1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="0"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView12"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_weight="0"
app:srcCompat="@drawable/findimage1" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical|left"
android:text="小宋,小丁,小张"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
2.3 数据类FcircleCard
数据类FcircleCard应包括头像id,昵称,配图id,文本,以及对应的返回函数,代码如下:
package com.example.wechatdemo;
public class FcircleCard {
public int touxiangid; // 头像id
public String name; //昵称
public String text; //文本
public int pictureid;//配图id
public FcircleCard(){
this.touxiangid=touxiangid;
this.name=name;
this.text=text;
this.pictureid=pictureid;
}
public String getName(){
return name;
}
public int getTouxiangid(){
return touxiangid;
}
public String getText(){return text;}
public int getPictureid(){return pictureid; }
}
2.4 FcircleAdapter
需要创建适配器findAdapter继承RecyclerView.Adapter,实现泛型传入RecyclerView.ViewHolder类,初始化item的控件,重写RecyclerView.Adapter类的相关方法,绑定控件对应的数据等,具体见RecyclerView的具体使用相关介绍。
package com.example.wechatdemo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class FcircleAdapter extends RecyclerView.Adapter<FcircleAdapter.MyViewHolder> {
private Context context;
public View itemView;
ArrayList<FcircleCard> list=new ArrayList<>();
//构造函数
public FcircleAdapter(Context context, ArrayList<FcircleCard> list) {
this.context=context;
this.list=list;
}
//创建ViewHolder,返回每一项的布局
@NonNull
@Override
public FcircleAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
itemView= LayoutInflater.from(context).inflate(R.layout.fcircle,parent,false);
MyViewHolder myViewHolder=new MyViewHolder(itemView);
return myViewHolder;
}
//将数据与 item 视图进行绑定
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
FcircleCard fcircleCard=list.get(position);
//绑定item每一个控件对应的数据
holder.imageView1.setImageResource(fcircleCard.getTouxiangid());
holder.imageView2.setImageResource(fcircleCard.getPictureid());
holder.textView1.setText(fcircleCard.name);
holder.textView2.setText(fcircleCard.text);
}
//返回item总条数
@Override
public int getItemCount() {
return list.size();
}
//内部类,绑定控件
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView1,imageView2;
private TextView textView1,textView2;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
imageView1=itemView.findViewById(R.id.imageView_touxiang);
imageView2=itemView.findViewById(R.id.imageView_picture);
textView1=itemView.findViewById(R.id.textView_name);
textView2=itemView.findViewById(R.id.textView_wenben);
}
}
}
2.5 FcircleActivity
新建FcircleActivity.java,供朋友圈调用intent跳转使用。在FcircleActivity中,要实现对item数据的初始化,适配器实例化,设置纵向布局等,具体见RecyclerView使用相关介绍。
package com.example.wechatdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.os.Bundle;
import android.widget.Adapter;
import java.util.ArrayList;
public class FcircleActivity extends AppCompatActivity {
private RecyclerView recyclerView;//声明RecyclerView
private FcircleAdapter fcircleAdapter;
private Context context;
ArrayList<FcircleCard> list=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
context = this;
setContentView(R.layout.activity_fcircle);
recyclerView = (RecyclerView) findViewById(R.id.RecyclerView_fcircle);
//初始化数据
initView();
//适配器实例化
fcircleAdapter = new FcircleAdapter(context,list);
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(fcircleAdapter);
//给recyclerView设置水平分割线
recyclerView.addItemDecoration(new DividerItemDecoration(context,DividerItemDecoration.HORIZONTAL_LIST,5,0xCCCCCCFF));
}
private void initView(){
String[] name={"小马","小丁"};
String[] text={"哈哈哈哈哈","芜湖芜湖"};
int[] touxiangid={R.drawable.photo_p1,R.drawable.photo_p2};
int[] pictureid={R.drawable.photo_p3,R.drawable.photo_p4};
for(int i=0;i<2;i++){
FcircleCard fcircleCard=new FcircleCard();
fcircleCard.name=name[i];
fcircleCard.text=text[i];
fcircleCard.touxiangid=touxiangid[i];
fcircleCard.pictureid=pictureid[i];
list.add(fcircleCard);
}
}
}
到这里,朋友圈的界面布局已处理完成。
3、 听一听界面布局
3.1 listen.xml
新建一个listen.xml,为听一听界面进行布局。
该界面仿音乐播放器设计,效果如下:
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:background="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<TextView
android:id="@+id/song"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="歌曲"
android:textSize="30sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imageView9"
android:layout_width="253dp"
android:layout_height="43dp"
android:layout_gravity="center"
android:layout_weight="1"
app:srcCompat="@android:drawable/status_bar_item_background" />
<TextView
android:id="@+id/lyric"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="歌词"
android:textSize="30sp" />
</LinearLayout>
<ImageView
android:id="@+id/imageView7"
android:layout_width="match_parent"
android:layout_height="187dp"
android:layout_weight="1"
app:srcCompat="@drawable/songimage1" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="66dp"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/song_name"
android:layout_width="match_parent"
android:layout_height="67dp"
android:layout_weight="0"
android:gravity="center"
android:text="水星记"
android:textSize="34sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView8"
android:layout_width="match_parent"
android:layout_height="62dp"
android:layout_weight="0"
android:gravity="center"
android:text="郭顶"
android:textSize="34sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="171dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_weight="1"
app:srcCompat="@android:drawable/ic_media_previous" />
<ImageView
android:id="@+id/imageView5"
android:layout_width="119dp"
android:layout_height="64dp"
android:layout_gravity="center"
android:layout_weight="1"
app:srcCompat="@android:drawable/ic_media_pause" />
<ImageView
android:id="@+id/imageView6"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_weight="1"
app:srcCompat="@android:drawable/ic_media_next" />
</LinearLayout>
</LinearLayout>
3.2 ListenActivity
ListenActivity代码较简单,直接指定其布局文件为listen.xml即可。
package com.example.wechatdemo;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
public class ListenActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.listen);
}
}
到这里,看一看界面的布局处理已完成。
4、 发现界面的RecyclerView布局
对发现界面进行布局,不仅要为其添加一个recyclerView,还需要为其Item设计布局格式。
4.1 fragment_find.xml
由于需要在发现界面进行RecyclerView布局,故添加一个RecyclerView,并设置其id,以便后面使用。
<?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"
tools:context=".findFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/RecyclerView_find"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
4.2 item对应布局文件(find.xml)
新建一个find.xml,为发现界面的RecyclerView内的元素设定xml样式。
放入一个水平向的linearLayout,添加一个放图标的ImageView,一个放名称的TextView,一个放右箭头图标的ImageView;再根据具体情况调整文字大小,整个LinearLayout的width、height等。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="80dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:id="@+id/finditem_linearlayout">
<ImageView
android:id="@+id/imageView_finditem"
android:layout_width="12dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
tools:srcCompat="@drawable/findimage1" />
<TextView
android:id="@+id/textView_finditem"
android:layout_width="230dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical|left"
android:text="TextView"
android:textSize="20sp" />
<ImageView
android:id="@+id/imageView_jiantou"
android:layout_width="6dp"
android:layout_height="30sp"
android:layout_gravity="center"
android:layout_weight="1"
android:rotation="0"
android:rotationX="44"
android:rotationY="0"
app:srcCompat="@drawable/jiantou" />
</LinearLayout>
</LinearLayout>
4.3 数据类Find_Item
数据类Find_Item应包括图标id,名称,右箭头id,以及对应的返回函数,代码如下:
package com.example.wechatdemo;
public class Find_Item {
public int imageid; // 图标id
public String name; //图标名称 如朋友圈
public int imageid_jiantou; //箭头id
public Find_Item(){
this.imageid=imageid;
this.name=name;
this.imageid_jiantou=imageid_jiantou;
}
public String getName(){return name; }
public int getImageid(){return imageid; }
public int getImageid_jiantou(){return imageid_jiantou;}
}
4.4 findAdapter
需要创建适配器findAdapter继承RecyclerView.Adapter,实现泛型传入RecyclerView.ViewHolder类,初始化item的控件,重写RecyclerView.Adapter类的相关方法,绑定控件对应的数据等。
package com.example.wechatdemo;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class findAdapter extends RecyclerView.Adapter<findAdapter.MyViewHolder> {
private Context context;
public View itemView;
ArrayList<Find_Item> list=new ArrayList<>();//使用
ArrayList<Intent> intents=new ArrayList<>();
//构造函数
public findAdapter(Context context, ArrayList<Find_Item> list , ArrayList<Intent> intents){
this.context=context;
this.list=list;
this.intents = intents;
}
//创建ViewHolder,返回每一项的布局
public findAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
itemView= LayoutInflater.from(context).inflate(R.layout.find,parent,false);
MyViewHolder myViewHolder=new MyViewHolder(itemView);
return myViewHolder;
}
//将数据与 item 视图进行绑定
@Override
public void onBindViewHolder(@NonNull findAdapter.MyViewHolder holder, int position) {
Find_Item find_item=list.get(position);
Intent intent=intents.get(position);
//绑定item每一个控件对应的数据
holder.textView1.setText(find_item.name);//文本一朋友圈
holder.imageView1.setImageResource(find_item.getImageid());//图标ID
holder.imageView2.setImageResource(find_item.getImageid_jiantou());//右箭头图片ID
//给item设置点击事件
holder.Clickitem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
context.startActivity(intent);
}
});
}
//返回item总条数
@Override
public int getItemCount() {
return list.size();
}
//内部类,绑定控件
class MyViewHolder extends RecyclerView.ViewHolder{
TextView textView1;
ImageView imageView1,imageView2;
View Clickitem;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
textView1=itemView.findViewById(R.id.textView_finditem);
imageView1=itemView.findViewById(R.id.imageView_finditem);
imageView2=itemView.findViewById(R.id.imageView_jiantou);
Clickitem=itemView.findViewById(R.id.finditem_linearlayout);
}
}
}
在这里实现跳转最最重要的类(也可以说是一种绑定机制)Intent出现了!
Intent在activity调用方面的使用并不复杂,先创建对象,再设置参数,再进行调用即可,在该模块,其被用到item点击事件中,故需对findAdapter进行以下操作:
//由于存在多个点击事件,使用不同的intent,故需要和数据列表Find_Item一样构造intent列表
ArrayList<Intent> intents=new ArrayList<>();
//在构造函数中传入Intent列表类型的参数
public findAdapter(Context context, ArrayList<Find_Item> list , ArrayList<Intent> intents){
this.context=context;
this.list=list;
this.intents = intents;
}
//在绑定控件函数中获取item的position,进行intent定义,并在点击事件中进行intent调用,从而启动item对应的activity
@Override
public void onBindViewHolder(@NonNull findAdapter.MyViewHolder holder, int position) {
Intent intent=intents.get(position);
//给item设置点击事件
holder.Clickitem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
context.startActivity(intent);
}
});
}
4.5 findFragment
在findFragment中,不仅要实现对item数据的初始化,还要对intent列表数组intents进行初始化,将intents的具体值(即其会调用哪个Activity)传递给findAdapter,从而实现点击跳转的效果,再适配器实例化,设置纵向布局。
package com.example.wechatdemo;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.app.Fragment;
import android.widget.LinearLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Collections;
public class findFragment extends Fragment {
private RecyclerView recyclerView;//声明RecyclerView
private findAdapter findAdapter;
private Context context;
ArrayList<Find_Item> list=new ArrayList<>();
ArrayList<Intent> intents=new ArrayList<>();
public findFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.fragment_find,container,false);
super.onCreate(savedInstanceState);
context = this.getActivity();
recyclerView = view.findViewById(R.id.RecyclerView_find);
//初始化数据
initView();
//初始化Intent
initIntent();
//适配器实例化,设置纵向布局
findAdapter = new findAdapter(context,list,intents);
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(findAdapter);
//给recyclerView设置水平分割线
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.HORIZONTAL_LIST,5,0xCCCCCCFF));
return view;
}
private void initView(){
String name[]={"朋友圈","听一听"};
int iamgeid[]={R.drawable.findimage1,R.drawable.findimage3};
//设置循环体传递数据
for (int i=0;i<2;i++){
Find_Item find_item=new Find_Item();
find_item.name=name[i];
find_item.imageid=iamgeid[i];
find_item.imageid_jiantou=R.drawable.jiantou;
list.add(find_item);
}
}
private void initIntent(){
Intent intent=new Intent(context,FcircleActivity.class);
intents.add(intent);//朋友圈界面跳转
Intent intent1=new Intent(context,ListenActivity.class);
intents.add(intent1);//听一听界面跳转
}
}
到这里,发现界面布局处理已经完成,跳转功能也已实现。
三、效果展示
发现界面:
朋友圈界面:
听一听界面:
跳转动画:
四、总结
本次的Project也非常有意思,让我对AS产生了更多兴趣,在一步步的丰富中,我看着我的Demo变得逐渐丰富起来,比较有成就感。
在这一次功能设计中,我先将整体功能构想计划好,根据功能添加文件,根据设计诉求添加布局,思路比开发第一部分功能时更加清晰。我对RecycleView、实现关键功能的相关组件的使用更熟练。
希望在下一次的功能设计中,我可以收获更多,冲鸭!!!🆗