预期目标:
设计一个app的门户框架,需要实现3-4个tab切换效果;
功能的实现要求需要的技术为:activity、xml、fragment;
在任一tab页中实现列表效果(本功能的实现需要使用recycleview)。
使用的软件:Andriod Studio
设计思路:
1.实现类微信界面:
将界面分为上、中、下三个子布局,分别为top.xml, tab.xml, button.xml文件,
中间部分的内容分别为tab1.xml,tab2.xml, tab3.xml,tab4.xml。
2.实现列表效果:
将任一tab页面的内容替换成列表。
设计过程:
一、xml页面布局
XML文件被广泛用于定义Android应用程序的用户界面布局。通过XML可以描述界面中的视图组件、其相对位置关系、样式和属性等。Android使用一种叫做"层叠布局"的方式来解析和渲染这些XML布局文件,从而实现应用程序界面的显示。
1.设计头部布局top.xml
根元素:布局的根元素是一个LinearLayout,通过xmlns属性指定了命名空间。
LinearLayout属性:LinearLayout的属性设置为android:layout_width="match_parent"
和android:layout_height="match_parent"
,意味着它会占据父容器(通常是屏幕)的全部宽度和高度。
子视图TextView:FrameLayout中添加了一个TextView作为子视图。TextView是一个文本视图,用于显示文本内容。
TextView属性:TextView的属性设置如下:
android:id="@+id/微信":为TextView指定了一个唯一的ID。
android:layout_width="match_parent"和android:layout_height="wrap_content":将TextView的宽度设置为与父容器相同,高度根据内容自适应。
android:layout_weight="1":LinearLayout中有多个子视图时,通过设置权重来占据剩余空间的比例,这里将TextView的权重设置为1。
android:background="#4CAF50":设置TextView的背景颜色为绿色。
android:gravity="center":设置文本内容在TextView中的居中对齐。
android:text="微信":设置TextView的文本内容为"微信"。
android:textColor="@color/white":设置文本颜色为白色。
android:textSize="40sp":设置文本大小为40sp 。
<?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">
<TextView
android:id="@+id/微信"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#4CAF50"
android:gravity="center"
android:text="微信"
android:textColor="@color/white"
android:textSize="40sp" />
</LinearLayout>
设计界面展示:
2.设计底部布局bottun.xml
先创建一个水平布局的LinearLayout
作为父容器,再创建四个垂直布局的LinearLayout子布局,
子布局包含一个图片视图和一个居中对齐的文本视图。
-
根元素:布局的根元素是一个LinearLayout。
-
LinearLayout属性:LinearLayout的属性设置为
android:layout_width="match_parent"
和android:layout_height="wrap_content"
,意味着它会占据父容器的全部宽度,高度根据内容自适应。 -
LinearLayout:android:orientation="horizontal",布局中组件的排列方式,有horizontal(水平)和vertical(垂直)两种方式。
-
子视图LinearLayout1:第一个LinearLayout作为一个底部导航栏中的一个按钮,设置与父容器宽度相等的宽度,并设置权重为1。
-
ImageView:LinearLayout1中添加了一个ImageView,用于显示一个图标。ImageView的属性设置如下:
android:id="@id/imageView1"
:为ImageView指定了一个唯一的ID。android:layout_width="match_parent"
和android:layout_height="wrap_content"
:将ImageView的宽度设置为与父容器相同,高度根据内容自适应。android:contentDescription="消息"
:设置图标的内容描述为"消息"。android:src="@android:drawable/ic_menu_send"
:设置图标的资源为系统提供的ic_menu_send图标。
-
TextView:LinearLayout1中添加了一个TextView,用于显示一个文本标签。TextView的属性设置如下:
android:id="@+id/textView1"
:为TextView指定了一个唯一的ID。android:layout_width="match_parent"
和android:layout_height="wrap_content"
:将TextView的宽度设置为与父容器相同,高度根据内容自适应。android:gravity="center"
:设置文本内容在TextView中的居中对齐。android:text="消息"
:设置TextView的文本内容为"消息"。android:textSize="25sp"
:设置文本大小为25sp。
其他三个LinearLayout中分别包含一个ImageView和一个TextView,用于显示不同的图标和文本标签。
<?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:id="@+id/bottun"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="消息"
android:src="@android:drawable/ic_menu_send" />
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="消息"
android:textSize="25sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/imageView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="联系人"
android:src="@android:drawable/ic_menu_call" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="联系人"
android:textSize="25sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/imageView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="设置"
android:src="@android:drawable/ic_menu_preferences" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="设置"
android:textSize="25sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/imageView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="朋友圈"
android:src="@android:drawable/ic_menu_gallery" />
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="朋友圈"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
设计界面展示:
3.设计中间布局fragment_1.xml
FrameLayout是一种布局容器,用于在Android应用程序中展示视图。允许子视图被放置在堆叠顺序中,进而进行界面整合。
-
FrameLayout属性:FrameLayout的属性设置如下:
android:layout_width="match_parent"
和android:layout_height="match_parent"
:设置FrameLayout的宽度和高度都为与父容器匹配。 -
TextView:在FrameLayout中添加了一个TextView作为子视图,用于显示文本内容。TextView的属性设置如下:
android:layout_width="match_parent"
和android:layout_height="match_parent"
:将TextView的宽度和高度都设置为与父容器匹配,填满整个FrameLayout。android:textSize="45dp"
:设置文本大小为45dp。android:text="这是微信界面"
:设置文本内容为"这是微信界面"。android:gravity="center"
:设置文本内容在TextView中的居中对齐。
<?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"
android:orientation="horizontal"
tools:context=".Fragment1">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="45dp"
android:text="这是微信界面"
android:gravity="center"/>
</FrameLayout>
设计界面展示:
4.tab布局(tab1.xml、tab2.xml、tab3.xml、tab4.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">
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:gravity="center"
android:text="这是聊天界面!"
android:textSize="45dp"/>
</LinearLayout>
tab1设计界面展示:
5.设计整合布局main_Activity.xml
-
LinearLayout属性:LinearLayout的属性设置如下:
android:layout_width="match_parent"
和android:layout_height="match_parent"
:设置LinearLayout的宽度和高度都为与父容器匹配。android:orientation="vertical"
:设置LinearLayout的子视图垂直排列。
-
include元素:include元素用于将其他布局文件引入到当前布局中,实现布局的复用性。在这个示例中,有两个include元素:
- 第一个include元素引用了名为"top"的布局文件,并将其作为LinearLayout的子视图。通过
layout="@layout/top"
指定引入的布局文件路径。 - 第二个include元素引用了名为"bottun"的布局文件,并将其作为LinearLayout的子视图。通过
layout="@layout/bottun"
指定引入的布局文件路径。
- 第一个include元素引用了名为"top"的布局文件,并将其作为LinearLayout的子视图。通过
-
FrameLayout:LinearLayout中的第三个元素是一个FrameLayout,用于显示内容。FrameLayout的属性设置如下:
android:layout_width="match_parent"
和android:layout_height="0dp"
:将FrameLayout的宽度设置为与父容器匹配,并将高度设置为0dp。android:layout_weight="1"
:设置FrameLayout在垂直方向上占据剩余空间。
该布局文件实现了一个垂直排列的界面,包含一个顶部布局、一个可变内容区域的FrameLayout和一个底部布局。顶部和底部布局通过include引入,而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="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<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="0dp"
android:layout_weight="1">
</FrameLayout>
<include
layout="@layout/bottun" />
</LinearLayout>
整合布局界面展示:
二、创建Java文件
创建4个Fragment文件:
当在Android应用中使用Fragment时,通常会在布局文件中包含一个用于容纳Fragment的FrameLayout,并在代码中将具体的Fragment添加到该容器中。
在每个Fragment中添加相应的tab:
Fragment1:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.tab1, container, false);
}
onCreateView() ,通过 LayoutInflater 将 XML 布局文件 R.layout.tab1 实例化为一个 View 对象,并将其返回作为 Fragment 的视图。inflater.inflate() 方法的第三个参数是一个布尔值,表示是否将生成的 View 添加到 container 容器中。
MainActivity:实现导航栏和 Fragment布局 切换功能
1.在onCreate中定义四个 Fragment:Fragment1
、Fragment2
、Fragment3
和 Fragment4。用来实现tab.xml界面显示。
2.定义FragmentManager 类型的变量 fm,用于管理 Fragment 对象的生命周期和切换操作。
3.定义四个 LinearLayout 类型的变量:linearLayout1、linearLayout2、linearLayout3 和 linearLayout4,通过findViewById方法找到FrameLayout容器,实现button.xml界面显示。
fragment1=new Fragment1();
fragment2=new Fragment2();
fragment3=new Fragment3();
fragment4=new Fragment4();
fm=getSupportFragmentManager();
linearLayout1=findViewById(R.id.LinearLayout1);
linearLayout2=findViewById(R.id.LinearLayout2);
linearLayout3=findViewById(R.id.LinearLayout3);
linearLayout4=findViewById(R.id.LinearLayout4);
4.定义initial()
方法用于初始化 Fragment。
-
获取FragmentManager实例:通过
FragmentManager fm = this.getSupportFragmentManager();
获取FragmentManager实例。 -
开启一个Fragment事务:通过
fm.beginTransaction()
开启一个Fragment事务,并获取到对应的FragmentTransaction对象。 -
添加Fragment到事务中:通过
add
方法向事务中添加对应的Fragment实例,这里将四个Fragment都添加到了同一个事务中,并且都添加到了名为content
的布局容器中。 -
提交事务:通过调用
commit
方法提交事务,将添加操作生效。
private void initial() {
FragmentTransaction ft=fm.beginTransaction()
.add(R.id.content,fragment1)
.add(R.id.content,fragment2)
.add(R.id.content,fragment3)
.add(R.id.content,fragment4);
ft.commit();
}
5.定义Fragmenthide()用于隐藏Fragment,将所有的fragment界面都隐藏,避免重叠显示。
private void fragmenthide() {
FragmentTransaction ft=fm.beginTransaction()
.hide(fragment1)
.hide(fragment2)
.hide(fragment3)
.hide(fragment4);
ft.commit();
}
6.定义fragmentshow(),用于展示Fragment相应的tab.xml界面。
private void fragmentshow(Fragment fragment) {
FragmentTransaction transaction=fm.beginTransaction()
.show(fragment);
transaction.commit();
}
7.定义onClick()
实现了 View.OnClickListener
接口,用于处理底部导航栏中选项的点击事件。
public void onClick(View view)
{
fragmenthide();
/*switch (view.getId())
{
case R.id.LinearLayout1 : fragmentshow(fragment1);
case R.id.LinearLayout2 : fragmentshow(fragment2);
case R.id.LinearLayout3 : fragmentshow(fragment3);
case R.id.LinearLayout4 : fragmentshow(fragment4);
default: break;
}*/
if (view.getId()==R.id.LinearLayout1)
fragmentshow(fragment1);
else if (view.getId()==R.id.LinearLayout2) {
fragmentshow(fragment2);
} else if (view.getId()==R.id.LinearLayout3) {
fragmentshow(fragment3);
} else if (view.getId()==R.id.LinearLayout4) {
fragmentshow(fragment4);
}
}
整合代码:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
Fragment fragment1;
Fragment fragment2;
Fragment fragment3;
Fragment fragment4;
FragmentManager fm;
FragmentTransaction ft;
LinearLayout linearLayout1,linearLayout2,linearLayout3,linearLayout4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragment1=new Fragment1();
fragment2=new Fragment2();
fragment3=new Fragment3();
fragment4=new Fragment4();
fm=getSupportFragmentManager();
linearLayout1=findViewById(R.id.LinearLayout1);
linearLayout2=findViewById(R.id.LinearLayout2);
linearLayout3=findViewById(R.id.LinearLayout3);
linearLayout4=findViewById(R.id.LinearLayout4);
initial();
fragmenthide();
fragmentshow(fragment1);
linearLayout1.setOnClickListener(this);
linearLayout2.setOnClickListener(this);
linearLayout3.setOnClickListener(this);
linearLayout4.setOnClickListener(this);
}
private void fragmenthide() {
FragmentTransaction ft=fm.beginTransaction()
.hide(fragment1)
.hide(fragment2)
.hide(fragment3)
.hide(fragment4);
ft.commit();
}
private void initial() {
FragmentTransaction ft=fm.beginTransaction()
.add(R.id.content,fragment1)
.add(R.id.content,fragment2)
.add(R.id.content,fragment3)
.add(R.id.content,fragment4);
ft.commit();
}
public void onClick(View view)
{
fragmenthide();
/*switch (view.getId())
{
case R.id.LinearLayout1 : fragmentshow(fragment1);
case R.id.LinearLayout2 : fragmentshow(fragment2);
case R.id.LinearLayout3 : fragmentshow(fragment3);
case R.id.LinearLayout4 : fragmentshow(fragment4);
default: break;
}*/
if (view.getId()==R.id.LinearLayout1)
fragmentshow(fragment1);
else if (view.getId()==R.id.LinearLayout2) {
fragmentshow(fragment2);
} else if (view.getId()==R.id.LinearLayout3) {
fragmentshow(fragment3);
} else if (view.getId()==R.id.LinearLayout4) {
fragmentshow(fragment4);
}
}
private void fragmentshow(Fragment fragment) {
FragmentTransaction transaction=fm.beginTransaction()
.show(fragment);
transaction.commit();
}
}
完整界面展示:
三、实现列表效果
1.修改tab2.xml(联系人)界面
修改为recycleview布局
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
</LinearLayout>
2.新建item.xml,设计列表布局格式,做为内容容器填充到recyclerview中去
<?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">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView"
android:textColor="@color/black"
android:textSize="35sp" />
</LinearLayout>
3.添加Myadapter.java,用于将数据绑定到 RecyclerView 中进行显示。
package com.example.myapplication;
import android.content.Context;
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;
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
public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context1).inflate(R.layout.item,parent,false);
Myholder holder = new Myholder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull Myholder holder, int position) {
holder.textView.setText(list1.get(position));
}
@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.textView1);
}
}
}
4.对Fragment2.java(联系人界面)进行修改
-
创建视图:通过LayoutInflater的inflate方法将布局文件tab2(R.layout.tab2)转换为View对象,并传入了container(父容器)和false(是否将返回的View添加到父容器中)。
-
初始化RecyclerView:获取到视图中的RecyclerView控件,并将其与成员变量recyclerView关联。
-
创建数据列表:初始化了一个空的ArrayList,并使用循环向其中添加了9个字符串元素。
-
创建适配器并设置给RecyclerView:实例化了MyAdapter适配器,并将上下文和数据列表传入构造函数。然后将适配器设置给RecyclerView。
-
设置RecyclerView布局管理器:创建LinearLayoutManager布局管理器的实例manager,并将其方向设置为垂直。最后将布局管理器设置给RecyclerView。
package com.example.myapplication;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class Fragment2 extends Fragment{ //继承自Fragment类的Fragment3类。在该类中,重写了onCreateView方法用于创建视图
private RecyclerView recyclerView;
private List<String> list= new ArrayList<>();
private Context context;
private Myadapter myadapter;
@SuppressLint("MissingInflatedId")
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View view=inflater.inflate(R.layout.tab2,container,false);
context=view.getContext();
recyclerView=view.findViewById(R.id.recycleview);
list=new ArrayList();
for (int i=0; i<9;i++)
{
list.add("这是第"+i+"行数据");
}
myadapter = new Myadapter(context,list);
recyclerView.setAdapter(myadapter);
LinearLayoutManager manager=new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
return view;
}
}
界面展示:
四、总结
1.高版本的AS中,默认情况下资源 id 将是非final 的,使用它们在 switch case 语句中可能会导致编译错误。使用 if-else 语句更具灵活性,并且通常不会受到工具链和编译器的限制。
2.特别注意界面设计的id,不要重名。
3.巧用快速修复,大部分问题都能被快速修复。