实验目标:
1.设计一个app的门户框架,需要实现3-4个tab切换效果
2.在任一tab页中实现列表效果
技术说明:
1.目标1实现需要的技术为:activity、xml、fragment
2.目标2实现需要使用recycleview
实现思路:
1.实现微信界面
将每个微信界面都分为上、中、下三个子布局,上下分别是top和buttom.xml文件,中间部分因为有四个微信界面,所以是tab1、tab2、tab3、tab4四个xml文件
2.实现列表效果
在任一tab.xml中添加recyclerview控件实现列表功能
大致就是以下文件:
实现过程:
1.头部布局top.xml
top布局就比较简洁,添加一个textview控件即可
<?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/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center"
android:text="微信"
android:textColor="@color/white"
android:textSize="25sp" />
</LinearLayout>
2.底部布局buttom.xml
buttom布局因为是图在上,文字在下的显示效果,所以需要利用水平布局的LinearLayout
作为父容器,再创建四个垂直布局的LinearLayout子布局,每个
子布局包含一个图片视图和一个居中对齐的文本视图
<?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:layout_gravity="bottom">
<!--这里我是想要显示在底部,所以设置成了bottom属性 -->
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:id="@+id/weixinimg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
app:srcCompat="@android:drawable/ic_menu_always_landscape_portrait"
tools:srcCompat="@android:drawable/ic_menu_always_landscape_portrait" />
<TextView
android:id="@+id/weixinview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center"
android:text="聊天"
android:textColor="@color/white"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:id="@+id/friendimg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
app:srcCompat="@android:drawable/ic_menu_call"
tools:srcCompat="@android:drawable/ic_menu_call" />
<TextView
android:id="@+id/friendview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center"
android:text="联系人"
android:textColor="@color/white"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:id="@+id/actimg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
app:srcCompat="@android:drawable/ic_menu_edit"
tools:srcCompat="@android:drawable/ic_menu_edit" />
<TextView
android:id="@+id/actview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center"
android:text="动态"
android:textColor="@color/white"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:id="@+id/personimg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/black"
app:srcCompat="@android:drawable/ic_menu_myplaces"
tools:srcCompat="@android:drawable/ic_menu_myplaces" />
<TextView
android:id="@+id/personview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center"
android:text="我的"
android:textColor="@color/white"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
界面效果如下:
3.中间布局tab.xml
布局内容比较简洁,添加文本显示即可,四个布局类似,此处仅列举一个
<?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"
tools:context=".tab2">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="30sp"
android:text="这是微信联系人界面" />
</FrameLayout>
4.整合三个布局,实现基础界面
在main.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"
android:orientation="vertical">
<include layout="@layout/top" />
<FrameLayout
android:id="@+id/content1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2" />
<include layout="@layout/buttom" />
</LinearLayout>
显示效果如下:
5.补全java文件
在java文件夹中创建四个Fragment文件(会自动生成xml),选择Blank,例如我创建的是tab1,会生成对应的tab1.xml,如果已经创建过xml影响也不大
四个tab类似,这里只给出tab2的代码(创建Fragment时里面会有很多代码,当现阶段并不需要,所以只保留onCreateView即可):
package com.example.mys_app;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class tab2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.tab2, container, false);
}
}
6.MainActivity.java:实现微信界面和切换底部导航栏功能
变量定义:
四个Fragment类型的变量(因为创建Fragment时命名的是tab,所以定义的类型是tab):fragment1,fragment2,fragment3,fragment4;
四个LinearLayout变量:LinearLayout1,LinearLayout2,LinearLayout3,LinearLayout4;
FragmentManager变量fm:负责管理Fragment,对Fragment进行操作
tab1 fragment1;
tab2 fragment2;
tab3 fragment3;
tab4 fragment4;
FragmentManager fm;
LinearLayout LinearLayout1,LinearLayout2,LinearLayout3,LinearLayout4;
定义initial()方法对界面内容进行初始化:
private void initial(){
FragmentTransaction ft=fm.beginTransaction()
.add(R.id.content1,fragment1)
.add(R.id.content1,fragment2)
.add(R.id.content1,fragment3)
.add(R.id.content1,fragment4);
ft.commit();
}
定义framenthide()方法对界面的内容进行隐藏,因为不这样会导致四个界面的文本内容会一起出现,所以需要在点击之前先将文本都隐藏起来,点击后,再单独显示相对应的文本内容:
private void fragmenthide(){
FragmentTransaction ft=fm.beginTransaction()
.hide(fragment1)
.hide(fragment2)
.hide(fragment3)
.hide(fragment4);
ft.commit();
}
定义fragmentshow()方法,对界面内容进行显示:
private void fragmentshow(Fragment fragment){
FragmentTransaction transaction=fm.beginTransaction()
.show(fragment);
transaction.commit();
}
定义onClick()方法,实现点击底部导航栏切换并显示对应的文本内容:
也可以用switch—case语句代替if-else语句,但可能会报错,处理起来比较麻烦,如果报错,建议修改为if-else语句
public void onClick(View view){
fragmenthide();
int id = view.getId();
if (id == R.id.LinearLayout1) {
fragmentshow(fragment1);
} else if (id == R.id.LinearLayout2) {
fragmentshow(fragment2);
} else if (id == R.id.LinearLayout3) {
fragmentshow(fragment3);
} else if (id == R.id.LinearLayout4) {
fragmentshow(fragment4);
}
}v
完整代码:
package com.example.mys_app;
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 {
tab1 fragment1;
tab2 fragment2;
tab3 fragment3;
tab4 fragment4;
FragmentManager fm;
LinearLayout LinearLayout1,LinearLayout2,LinearLayout3,LinearLayout4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
fragment1=new tab1();
fragment2=new tab2();
fragment3=new tab3();
fragment4=new tab4();
LinearLayout1=findViewById(R.id.LinearLayout1);
LinearLayout2=findViewById(R.id.LinearLayout2);
LinearLayout3=findViewById(R.id.LinearLayout3);
LinearLayout4=findViewById(R.id.LinearLayout4);
fm=getSupportFragmentManager();
initial();
fragmenthide();
fragmentshow(fragment1);
LinearLayout1.setOnClickListener(this);
LinearLayout2.setOnClickListener(this);
LinearLayout3.setOnClickListener(this);
LinearLayout4.setOnClickListener(this);
}
private void initial(){
FragmentTransaction ft=fm.beginTransaction()
.add(R.id.content1,fragment1)
.add(R.id.content1,fragment2)
.add(R.id.content1,fragment3)
.add(R.id.content1,fragment4);
ft.commit();
}
public void onClick(View view){
fragmenthide();
int id = view.getId();
if (id == R.id.LinearLayout1) {
fragmentshow(fragment1);
} else if (id == R.id.LinearLayout2) {
fragmentshow(fragment2);
} else if (id == R.id.LinearLayout3) {
fragmentshow(fragment3);
} else if (id == R.id.LinearLayout4) {
fragmentshow(fragment4);
}
}
private void fragmenthide(){
FragmentTransaction ft=fm.beginTransaction()
.hide(fragment1)
.hide(fragment2)
.hide(fragment3)
.hide(fragment4);
ft.commit();
}
private void fragmentshow(Fragment fragment){
FragmentTransaction transaction=fm.beginTransaction()
.show(fragment);
transaction.commit();
}
}
显示效果:
到这里,简单微信界面的功能就已经完成了,下面展示列表功能的实现
7.列表功能
需要完成Myadapter.java和item.xml
我选择的是将列表展示在tab1界面上,所以会修改原来的tab1.java和tab1.xml中代码
新建item.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="wrap_content">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="TextView"
android:textColor="@android:color/holo_red_dark"
android:textSize="35sp" />
</LinearLayout>
修改tab1.xml,将列表显示在tab1界面上:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".tab1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
新建一个Myadapter.java文件,也就是适配器,这里是需要自己去定义才能使用的:
package com.example.mys_app;
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);
}
}
}
重新编写tab1.java,重写onCreateview()方法:
package com.example.mys_app;
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
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 tab1 extends Fragment{
Context context;
RecyclerView recyclerView;
View view;
List list;
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.tab1,container,false);
context=view.getContext();
recyclerView=view.findViewById(R.id.recyclerview);
list=new ArrayList();
for(int i=0;i<10;i++){
list.add("这是第"+i+"行数据");
}
Myadapter myadapter = new Myadapter(context,list);
recyclerView.setAdapter(myadapter);
LinearLayoutManager manager=new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
return view;
}
}
最后结果展示:
总结:
上面提到过的if-else和switch-case之间的问题,我一开始是用的后者,但报错解决不了就使用了if-else语句改写。这里报错是因为即使定义了变量为final,ADT or Gradle编译时也会将资源id(view id)做非final处理来避免项目资源id冲突,加快编译构建速度(取决于ADT和Gradle的版本)。
原本tab1.java里onCreateview方法里是这样写的,但由于onCreateview方法return的是一个view类型的结果,所以需要定义一个view类型的变量,去输出结果,就不用使用上述方框中的方法。