目标:
1.设计一个app的门户框架,需要实现3-4个tab切换效果;本功能要求需要的技术为: activity,xml、fragment;
2. 在任一tab页中实现列表效果;本功能的实现需要使用RecycleView;
3.博客末尾写明项目源码的线上仓库地址
实现的具体效果如下动图所示:
最上方为"微信",下方为4个bottom,在第一个界面除了fragment内容还有一个RecyclerView实现的列表效果。
技术说明:
Activity: 活动(Activity)是一个可视化的用户界面,负责创建一个屏幕窗口,放置 UI 组件,供用户交互。假如我们打开一个应用,看到的整个界面就是一个Activity,当点击一个超链接,跳转到另一个界面,则又是一个新的Activity。本次实验程序的Activity就是在创建一个屏幕窗口,并且在其中把fragment等组件的位置,点击监听等各种设置好。
Fragment: 直译为片段、碎片,是Android 3.0引入的组件,它不能单独使用,必须要依赖于Activity。 Fragment引入之前几乎所有的逻辑都被放置在Activity中,使得Activity会比较臃肿,Fragment作为一个微小的Activity诞生。通过使用fragment,我们可以按照模块将代码写入到不同的Fragment中,之后在根据需要嵌入到Activity。多个Activity也可以复用一个Fragment,此外,针对不同的情形也可以根据需要调用不同的Fragment,这比全部写在Activity中方便、简洁很多。在本次实验中就用到了4个fragment来实现四个界面"这是xxx界面"部分的内容。
xml: XML是一种可扩展标记语言,它被用来传输和存储数据。在Android中也会随处可见XML文件,包括一个android项目不可缺少的AndroidManifest.xml清单文件,res资源文件目录下的layout中。在安卓中可以实现非常丰富的作用,如设置布局,设置颜色,定义尺寸、画布等等作用。本次实验主要涉及到的是res下的layout(布局)的xml文件。
RecyclerView: RecycleView能够灵活实现大数据的展示,视图的复用管理比ListView更好,能够显示列表、网格、瀑布流等形式、不同的ViewHolder能够实现item多元化的功能。它是Android5.0之后新添加的控件,推出用来替代传统的ListView和GridView列表控件,目的是在有限的屏幕之上展示大量的内容,因此 RecyclerView 的复用机制的实现是它的一个核心部分。RecyclerView可以说是做Android应用开发使用最广的几个控件之一。
实验过程及主要代码解释:
资源文件(底部图标图片):
实验中要设置的XML文件一览:
实验中要编写的java文件一览:
布局设计
top.xml(顶部的布局效果)
控件:LinearLayout(线性布局)、textView
主要修改的属性及属性含义:
android:id="@+id/textView" //textView控件的id信息
android:layout_width="wrap_content" //设置控件宽度布局贴合内容
android:layout_height="wrap_content" //设置控件高度布局贴合内容
android:background="@color/black" //设置背景颜色(黑)
android:gravity="center" //设置文本在正中
android:text="微信" //设置文本内容
android:textColor="@color/white" //文本颜色
android:textSize="50sp" //设置文本大小
app:layout_constraintEnd_toEndOf="parent" //文本右边的约束布局依照'parent'
界面效果:
bottom.xml(底部的布局效果)
控件:LinearLayout(线性布局)、imageView、textView
主要修改的属性及属性含义:
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
//设置方向,水平/竖直
android:orientation="vertical"
//指定imageView用到的资源图片路径
android:src="@drawable/pngone
//控件id设置,便于后续编写java文件时通过id找到控件
android:id="@+id/linearlayout2"
android:id="@+id/imageView4"
android:id="@+id/textView9"
界面效果:
frangment1.xml(第一个界面的文本和列表效果)
控件:LinearLayout(线性布局)、recyclerview、textView
主要修改的属性及属性含义:
android:orientation="vertical"
android:layout_weight="1" //一旦View设置了该属性(有效的情况下),那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比
android:layout_gravity="center" //view相对于它父view的位置
android:gravity="center" //view里面的内容在这个view中的位置
android:text="这是微信界面"
android:textSize="40sp" //文本字体大小
界面效果:
frangment2(3、4).xml
fragment1、2、3、4都参与实现tab切换效果,fragment1多实现了任一tab页面的列表效果。所以frangment2(3、4).xml的内容基本类似:
控件: LinearLayout、textView
主要修改的属性及属性含义(基本都是上面提及过的属性,不再多做解释):
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:gravity="center"
android:textSize="40sp"
android:text="这是xxx的界面"
界面效果(只截取fragment2作为代表,3和4除具体文本显示外基本类似):
main_activity.xml(汇总整合)
控件: LinearLayout、FrameLayout(帧布局,以层叠的方式布局组件,每次只能显示其中的一个)
主要修改的属性及属性含义:
//包含进top.xml
<include
layout="@layout/top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</FrameLayout>
//包含进bottom.xml
<include
layout="@layout/botton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
界面效果:
item.xml(用于RecyclerView实现实例化列表的布局文件)
控件:
主要修改的属性及属性含义:
android:textColor="@color/orangered"
//注意这个颜色需要到res/values/color.xml下手动添加该颜色
界面效果:
JAVA代码编写:
MainActivity.java
把控件布局整合安排好,主要通过隐藏、显示特定fragment来实现点击切换tab效果。
(具体的关键代码解析都放在注释里了,如下:)
package com.example.homeworkone;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
//直接使用Activity作为事件监听器,实现监听器的接口.
public class MainActivity1 extends AppCompatActivity implements View.OnClickListener{
Fragment fragment1,fragment2,fragment3,fragment4;
LinearLayout linearLayout1,linearLayout2,linearLayout3,linearLayout4;
FragmentManager fm;
static final int l1=R.id.linearlayout1; //把linearlayout的id设为静态值(onClick()事件判断处理时用Switch报错时可能有用的解决方案)
// 本程序由于Switch()-case()分支不适用改用了if-else语句
static final int l2=R.id.linearlayout2;
static final int l3=R.id.linearlayout3;
static final int l4=R.id.linearlayout4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
fragment1=new fragment(); //通过编写的fragment类创建fragment1对象
fragment2=new fragment2(); //通过编写的fragment2类创建fragment2对象
fragment3=new fragment3(); //通过编写的fragment3类创建fragment3对象
fragment4=new fragment4(); //通过编写的fragment4类创建fragment4对象
linearLayout1=findViewById(R.id.linearlayout1); //通过id找到对应linearlayout1控件
linearLayout2=findViewById(R.id.linearlayout2); //通过id找到对应linearlayout2控件
linearLayout3=findViewById(R.id.linearlayout3); //通过id找到对应linearlayout3控件
linearLayout4=findViewById(R.id.linearlayout4); //通过id找到对应linearlayout4控件
fm=getSupportFragmentManager();
initial(); //声明fragment页面初始化的函数
fragmenthide(); //声明一个隐藏fragment页面,防止页面堆叠
fragmentshow(fragment1);//程序启动后将其他初始化时的add的fragment隐藏
// 只显示fragment1作为初始的显示界面
linearLayout1.setOnClickListener(this);//设置事件处理的监听器
linearLayout2.setOnClickListener(this);//设置事件处理的监听器
linearLayout3.setOnClickListener(this);//监听对屏幕的
linearLayout4.setOnClickListener(this);//监听对屏幕的
}
private void initial() {//给fragment页面初始化
FragmentTransaction ft=fm.beginTransaction()//每次对Fragment进行操作,都是通过FragmentTransaction这个类来实现
.add(R.id.content,fragment1)
.add(R.id.content,fragment2)
.add(R.id.content,fragment3)
.add(R.id.content,fragment4);
ft.commit(); //提交事务
}
private void fragmenthide() {//实现隐藏fragment的效果,可有效防止页面堆叠
FragmentTransaction ft=fm.beginTransaction()
.hide(fragment1)
.hide(fragment2)
.hide(fragment3)
.hide(fragment4);
ft.commit();
}
private void fragmentshow(Fragment fragment){
fragmenthide(); //显示指定fragment页面,隐藏其他fragment页面
FragmentTransaction ft=fm.beginTransaction()
.show(fragment);
ft.commit();
}
@Override //代表点击事件的处理函数,实现产生点击4个tab切换效果
public void onClick(View view) {
if (view.getId() == l1) {
fragmentshow(fragment1);
}
else if (view.getId() == l2) {
fragmentshow(fragment2);
}
else if (view.getId() == l3) {
fragmentshow(fragment3);
}
else if (view.getId() == l4) {
fragmentshow(fragment4);
}
}
}
Myadapter.java
这部分主要实现将数据源中多种多样的数据格式转化为RecyclerView可以展示的格式,建立数据源与RecyclerView的一个适配关系。
(具体的关键代码解析都放在注释里了)
package com.example.homeworkone;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import java.util.zip.Inflater;
public class Myadapter extends RecyclerView.Adapter<Myadapter.Myholder> {
Context context1;
List<String> list1;
//构造函数
public Myadapter(Context context,List list){
context1=context;
list1=list;
}
@NonNull
@Override
//在RecyclerView控件中,当需要新的View来展示列表项时,
// RecyclerView首先会调用Adapter中的onCreateViewHolder方法,
// 来创建一个ViewHolder并绑定相应的View。ViewHolder对象会缓存在RecyclerView中,以便重复利用
public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//LayoutInflater是用来找layout下xml布局文件,并且实例化,对于想要动态加载的界面,需要使用LayoutInflater.inflate()来载入。
View view=LayoutInflater.from(context1).inflate(R.layout.item,parent,false);
//需要加载资源的id为R.layout.item
Myholder myholder=new Myholder(view);
return myholder;
}
@Override
//onBindViewHolder方法会在RecyclerView进入屏幕时调用
public void onBindViewHolder(@NonNull Myholder holder, int position) {
holder.textView.setText(list1.get(position)); //将textView和相应位置的list绑定在一起
}
@Override//返回条目的个数
public int getItemCount() {
return list1.size();
}
public class Myholder extends RecyclerView.ViewHolder{
TextView textView;
public Myholder(@NonNull View itemView) {
super(itemView);
textView=itemView.findViewById(R.id.textView10); //根据item.xml里id为textView10的textView作为textView的值
}
}
}
fragment.java(对应fragment1.xml):
编程处理fragment1中的控件,与Myadapter共同实现tab列表效果,同时实现fragment页面效果。
(关键代码解析在下方注释)
package com.example.homeworkone;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import java.util.zip.Inflater;
public class Myadapter extends RecyclerView.Adapter<Myadapter.Myholder> {
Context context1;
List<String> list1;
//构造函数
public Myadapter(Context context,List list){
context1=context;
list1=list;
}
@NonNull
@Override
//在RecyclerView控件中,当需要新的View来展示列表项时,
// RecyclerView首先会调用Adapter中的onCreateViewHolder方法,
// 来创建一个ViewHolder并绑定相应的View。ViewHolder对象会缓存在RecyclerView中,以便重复利用
public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//LayoutInflater是用来找layout下xml布局文件,并且实例化,对于想要动态加载的界面,需要使用LayoutInflater.inflate()来载入。
View view=LayoutInflater.from(context1).inflate(R.layout.item,parent,false);
//需要加载资源的id为R.layout.item
Myholder myholder=new Myholder(view);
return myholder;
}
@Override
//onBindViewHolder方法会在RecyclerView进入屏幕时调用
public void onBindViewHolder(@NonNull Myholder holder, int position) {
holder.textView.setText(list1.get(position)); //将textView和相应位置的list绑定在一起
}
@Override//返回条目的个数
public int getItemCount() {
return list1.size();
}
public class Myholder extends RecyclerView.ViewHolder{
TextView textView;
public Myholder(@NonNull View itemView) {
super(itemView);
textView=itemView.findViewById(R.id.textView10); //根据item.xml里id为textView10的textView作为textView的值
}
}
}
fragment2、3、4.java
这部分比较简单,就只放一个做代表了
总结:
在设计App门户框架时,我通过使用activity和xml技术,成功地创建了一个具有多个Tab页的布局结构,并实现了Tab之间的切换效果。并使用了Fragment来管理每个Tab页的内容。在选定任一Tab页(实验中是fragment1)后,需要在该页中实现列表效果,并展示相关的信息。为了满足该需求,我使用了RecycleView组件,这是一种高效灵活的列表显示控件,需要使用适配器(Adapter)将数据源与其绑定,并通过自定义布局文件来定义列表项的样式。通过使用RecycleView,能够灵活地展示和管理列表中的数据,并为用户提供友好的滚动和交互体验。以上就是关于本次实验的主要内容和涉及到的知识总结,通过本次实验,我对这些控件布局设置的含义有了更深的理解,很有收获。