2023.03.31 补充该功能在 Fragment 中的使用方法:
Tip:使用Activity实现的直接看下面就行,不用看这一节代码
首先需要将CommentBottomDialog.java与Activity进行关联(我使用的是一个Activity管理多个Fragment),在Activity页将Fragment添加进容器 (有FragmentManager的话直接添加进容器即可,不用重新写一遍代码),下面是示例代码:
//获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
//开始事务
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//将Fragment添加到容器视图中
CommentBottomDialog commentBottomDialog = new CommentBottomDialog();
fragmentTransaction.add(R.id.oneLayout, commentBottomDialog);
//提交事务
fragmentTransaction.commit();
这时,在需要使用该功能的地方使用如下代码即可:
//创建MyBottomSheetDialogFragment的实例
CommentBottomDialog bottomSheet = new CommentBottomDialog();
//显示MyBottomSheetDialogFragment
bottomSheet.show(getFragmentManager(), "bottomDialog");
错误分析:
如果Fragment尚未添加到Activity中,使用 getContext() 方法和 requireContext() 方法将会返回null,此时再调用 getFragmentManager() 方法或 getSupportFragmentManager() 方法就会导致空指向异常。
所以在Fragment页面中实现此功能,原先就有FragmentManager的情况下要先将CommentBottomDialog.java,这个我们定义的Fragment文件添加进Activity中去,就可以顺利取到FragmentManager了。
以下是原文章:
实现效果
实现过程
先使用BottomSheetDialog实现页面从底部弹出效果
创建一个类CommentBottomDialog.java并继承:BottomSheetDialogFragment重写 onCreateDialog 方法:
package com.example.bottomsheetdialog1;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.jetbrains.annotations.NotNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class CommentsBottomDialog extends BottomSheetDialogFragment {
@NonNull
@NotNull
@Override
public Dialog onCreateDialog(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
if (getActivity() == null) return super.onCreateDialog(savedInstanceState);
// 第二个参数是设置 dialog 的背景样式
BottomSheetDialog dialog = new BottomSheetDialog(getActivity(), R.style.BottomSheetStyle);
// 这个是设置 dialog 弹出动画
Window window = dialog.getWindow();
if (window != null) {
window.setWindowAnimations(R.style.BottomSheetStyle);
}
// 设置 dialog 布局
initView(dialog);
return dialog;
}
private void initView(BottomSheetDialog dialog) {
View root = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_comment, null);
dialog.setContentView(root);
//设置高度
ViewGroup.LayoutParams params = root.getLayoutParams();
params.height = (int) (0.9 *
getResources().getDisplayMetrics().heightPixels);
root.setLayoutParams(params);
// 初始化 dialog 布局里的控件
ImageView iv_close = root.findViewById(R.id.iv_close);
// 点击关闭 dialog
iv_close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
}
}
创建CommentBottomDialog.java对应的XML布局文件dialog_comment.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:background="@drawable/shape"
android:padding="10dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/cardTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="16sp"
android:textColor="#000000"
android:text="评论" />
<ImageView
android:id="@+id/iv_close"
android:src="@drawable/close"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="#000000"/>
</LinearLayout>
在values文件夹中创建styles.xml文件并在其中创建BottomSheetStyle布局样式:
<!-- BottomDialog -->
<style name="BottomSheetStyle" parent="Theme.AppCompat.Dialog">
<!-- 背景透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 调暗 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 动画 -->
<item name="android:windowEnterAnimation">@anim/popup_in</item>
<item name="android:windowExitAnimation">@anim/popup_out</item>
</style>
在drawable文件夹中新建背景文件shape.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- rectangle表示为矩形 -->
<!-- 填充的颜色 -->
<solid android:color="@color/white" />
<!-- 边框的颜色和粗细 -->
<stroke
android:width="1dp"
android:color="@color/white" />
<!-- android:radius 关键点,圆角的半径 -->
<corners
android:radius="2dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp"
android:bottomRightRadius="0dp"
android:bottomLeftRadius="0dp" />
</shape>
在res文件夹下创建anim文件夹并新建两个动画文件:
文件名:popup_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%p"
android:toYDelta="0"
android:duration="400"/>
<alpha android:fromAlpha="0"
android:toAlpha="1.0"
android:duration="400"/>
</set>
文件名:popup_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0"
android:toYDelta="100%p"
android:duration="500"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0"
android:duration="500"/>
</set>
到此使用BottomSheetDialog实现底部弹出页面功能已经实现,直接调用以下代码即可:
CommentsBottomDialog bottomDialog = new CommentsBottomDialog();
bottomDialog.show(MainActivity.this.getSupportFragmentManager(), "bottomDialog");
再实现RecyclerView的功能
首先在弹窗布局文件dialog_comment.xml中加入RecyclerView控件:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
/>
创建Comments.java数据实体类:
package com.example.bottomsheetdialog1;
public class Comments {
private String content; //评论
private int imageId; //头像
public Comments(String name, int imageId){
this.content = name;
this.imageId = imageId;
}
public String getName() {
return content;
}
public int getImageId() {
return imageId;
}}
创建RecyclerView中要实现的布局文件comments_item.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="@+id/image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
创建适配器文件CommentsAdapter.java:
package com.example.bottomsheetdialog1;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
import androidx.recyclerview.widget.RecyclerView;
public class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.ViewHolder> {
//数据源,在new此类的时候传入
private List<Comments> mCommentsList;
//静态内部类,每个条目对应的布局
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView image;
TextView content;
public ViewHolder(View view) {
super(view);
image = (ImageView) view.findViewById(R.id.image);
content = (TextView) view.findViewById(R.id.content);
}
}
//CommentsAdapter的构造方法,加入了数据源参数,在构造的时候赋值给mCommentsList
public CommentsAdapter(List<Comments> commentsList) {
mCommentsList = commentsList;
}
//用于创建ViewHolder实例,并把加载的布局传入到ViewHolder的构造函数去
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.comments_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
//用于对子项的数据进行赋值,会在每个子项被滚动到屏幕内时执行。position得到当前项的Comments实例
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Comments comments = mCommentsList.get(position);
holder.image.setImageResource(comments.getImageId());
holder.content.setText(comments.getName());
}
//返回RecyclerView的子项数目
@Override
public int getItemCount() {
return mCommentsList.size();
}
}
先在CommentsBottomDialog.java文件中定义一个全局List:
private List<Comments> commentsList = new ArrayList<>();
之后在CommentsBottomDialog.java文件中创建一个方法造一些假数据用于测试功能:
//初始化数据
private void fakedata() {
for (int i = 0; i < 3; i++) {
Comments comments1 = new Comments("Test1", R.drawable.src);
commentsList.add(comments1);
Comments comments2 = new Comments("Test2", R.drawable.src);
commentsList.add(comments2);
Comments comments3 = new Comments("Test3", R.drawable.src);
commentsList.add(comments3);
Comments comments4 = new Comments("Test4", R.drawable.src);
commentsList.add(comments4);
Comments comments5 = new Comments("Test5", R.drawable.src);
commentsList.add(comments5);
Comments comments6 = new Comments("Test6", R.drawable.src);
commentsList.add(comments6);
Comments comments7 = new Comments("Test7", R.drawable.src);
commentsList.add(comments7);
Comments comments8 = new Comments("Test8", R.drawable.src);
commentsList.add(comments8);
Comments comments9 = new Comments("Test9", R.drawable.src);
commentsList.add(comments9);
Comments comments10 = new Comments("Test10", R.drawable.src);
commentsList.add(comments10);
}
}
之后在CommentsBottomDialog.java文件中的*initView()*方法中写入:
//初始化数据
fakedata();
//RecyclerView获取他的对象
RecyclerView recyclerView = root.findViewById(R.id.recycler_view);
//LayoutManager用于指定RecyclerView的布局方式
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
//给layoutManager的展示方式设置为竖直方向
layoutManager .setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
CommentsAdapter adapter = new CommentsAdapter(commentsList);
recyclerView.setAdapter(adapter);
至此,使用BottomSheetDialog和RecyclerView实现底部弹出评论区功能已经实现
全部代码
Tips:这里只放出在实现RecyclerView功能时有改动代码的代码,其余没放出的代码并未改动
dialog_comment.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:background="@drawable/shape"
android:padding="10dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/cardTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="16sp"
android:textColor="#000000"
android:text="评论" />
<ImageView
android:id="@+id/iv_close"
android:src="@drawable/close"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="#000000"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
/>
</LinearLayout>
CommentsBottomDialog.java:
package com.example.bottomsheetdialog1;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class CommentsBottomDialog extends BottomSheetDialogFragment {
private List<Comments> commentsList = new ArrayList<>();
@NonNull
@NotNull
@Override
public Dialog onCreateDialog(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
if (getActivity() == null) return super.onCreateDialog(savedInstanceState);
// 第二个参数是设置 dialog 的背景样式
BottomSheetDialog dialog = new BottomSheetDialog(getActivity(), R.style.BottomSheetStyle);
// 这个是设置 dialog 弹出动画
Window window = dialog.getWindow();
if (window != null) {
window.setWindowAnimations(R.style.BottomSheetStyle);
}
// 设置 dialog 布局
initView(dialog);
return dialog;
}
private void initView(BottomSheetDialog dialog) {
View root = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_comment, null);
dialog.setContentView(root);
//设置高度
ViewGroup.LayoutParams params = root.getLayoutParams();
params.height = (int) (0.9 *
getResources().getDisplayMetrics().heightPixels);
root.setLayoutParams(params);
// 初始化 dialog 布局里的控件
ImageView iv_close = root.findViewById(R.id.iv_close);
// 点击关闭 dialog
iv_close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
//初始化数据
fakedata();
//RecyclerView获取他的对象
RecyclerView recyclerView = root.findViewById(R.id.recycler_view);
//LayoutManager用于指定RecyclerView的布局方式
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
//给layoutManager的展示方式设置为竖直方向
layoutManager .setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
CommentsAdapter adapter = new CommentsAdapter(commentsList);
recyclerView.setAdapter(adapter);
}
//初始化数据
private void fakedata() {
for (int i = 0; i < 3; i++) {
Comments comments1 = new Comments("Test1", R.drawable.src);
commentsList.add(comments1);
Comments comments2 = new Comments("Test2", R.drawable.src);
commentsList.add(comments2);
Comments comments3 = new Comments("Test3", R.drawable.src);
commentsList.add(comments3);
Comments comments4 = new Comments("Test4", R.drawable.src);
commentsList.add(comments4);
Comments comments5 = new Comments("Test5", R.drawable.src);
commentsList.add(comments5);
Comments comments6 = new Comments("Test6", R.drawable.src);
commentsList.add(comments6);
Comments comments7 = new Comments("Test7", R.drawable.src);
commentsList.add(comments7);
Comments comments8 = new Comments("Test8", R.drawable.src);
commentsList.add(comments8);
Comments comments9 = new Comments("Test9", R.drawable.src);
commentsList.add(comments9);
Comments comments10 = new Comments("Test10", R.drawable.src);
commentsList.add(comments10);
}
}
}