Android开源框架CommentBottomBar底部评论弹窗

前言

通常在社交类型的APP上都会有这么一个需求,就是评论的时候通常要带有文字或者是文字+图片。针对这一需求设计了一款相关的控件CommentBottomBar。项目已发布Github,欢迎Star!
Github地址:https://github.com/EverZc/CommentBottomBar

目录

  1. 效果图
  2. 使用步骤
  3. 常用方法
  4. 实现原理

1.效果图

效果示例

2.使用步骤

Step 1.添加依赖CommentBottomBar

首先要在项目的根build.gradle下添加:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

然后要在要依赖的module中添加

dependencies {
    implementation 'com.github.EverZc:CommentBottomBar:latest.release.here'
}

Step 2.使用流程

CommentBottomBar使用起来非常简单

    //第一步:在需要评论的地方初始化控件
    ZBottomSheetPictureBar commentZBSP = ZBottomSheetPictureBar.delegation(MainActivity.this);
    //第二步:弹出底部评论栏,并设置EditText的hint
    commentZBSP.show("期待您的神回复");
    //第三步:设置控件内的点击回调(添加图片以及提交按钮)
    commentZBSP.setOnSeetBarOnClickListener(new ZBottomSheetPictureBar.OnSheetBarOnClickListener() {
        @Override
        public void onAddClick() {
            Intent intent = new Intent(MainActivity.this, ImagePickActivityPicker.class);
            intent.putExtra(IS_NEED_CAMERA, true);
            int maxNumber = commentZBSP.getAdapterData().isEmpty() ?
                    ZBottomConstant.ARTICLE_IMAGE_MAX : ZBottomConstant.ARTICLE_IMAGE_MAX - commentZBSP.getAdapterData().size();
            intent.putExtra(FilePicker.MAX_NUMBER, maxNumber);
            startActivityForResult(intent, ZBottomConstant.REQUEST_CODE_PICK_IMAGE);
        }

        @Override
        public void onCommitClick(ArrayList<ImageFile> images, EditText editText) {
          //此处是点击按钮,具体处理提交评论的文字以及图片
        }
    });

    //第四步:处理选择的图片,设置到弹窗控件中。
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case ZBottomConstant.REQUEST_CODE_PICK_IMAGE:
                //获取选择的图片
                if (resultCode == RESULT_OK) {
                    ArrayList<ImageFile> imageList = data.getParcelableArrayListExtra(FilePicker.RESULT_PICK_IMAGE);
                    commentZBSP.setImages(imageList);
                }
                break;
        }
    }

3.常用方法

方法名 描述
delegation(Context context) 创建方法
show(String hint) 弹出评论框并填写评论的hint
dismiss() 隐藏评论弹出框,并隐藏软键盘
setImages(ArrayList<ImageFile> images) 添加图片
getAdapterData() 获取当前评论框内的图片
getAdapter() 获取弹出框图片的adapter
getCommentText() 获取评论的内容
clear() 清理评论文本内容以及评论的图片内容

4.实现原理

ZBottomDialog说明

本底部评论弹窗自定义的ZBottomDialog采用Material Design的BottomSheetBehavior作为底部弹出框
首先简单了解一下使用到的相关内容。
对于BottomSheetBehavior弹出包含五种状态:

  • STATE_COLLAPSED:折叠状态,bottom sheets只在底部显示一部分布局。显示高度可以通过 app:behavior_peekHeight 设置(本框架未设置);
  • STATE_DRAGGING:过渡状态,此时用户正在向上或者向下拖动bottom sheet;
  • STATE_SETTLING: 视图从脱离手指自由滑动到最终停下的这一小段时间
  • STATE_EXPANDED: 完全展开的状态
  • STATE_HIDDEN: 隐藏状态。默认是false,可通过app:behavior_hideable属性设置是否能隐藏

为什么要重写BottomSheetDialog相关方法?
如果直接使用BottomSheetDialog会出现2个问题

  1. 初始化BottomSheetDialog后,在界面上只显示了评论文字,而评论下边的图片内容的RecyclerView部分需要单独上拉才能出现
  2. 在下滑了评论以及评论图片后,控件的view隐藏了,但是软键盘没有隐藏,整个dialog没有关闭。

问题1解决:需要设置当前dialog的style如下:
android:windowIsFloating必须为false
android:windowSoftInputMode为adjustResize
否则会导致显示不全

<style name="bottomSheetEdit" parent="Theme.Design.Light.BottomSheetDialog">    <item name="android:windowIsFloating">false</item>    <item name="android:statusBarColor">@android:color/transparent</item>    <item name="android:windowSoftInputMode">adjustResize</item></style>

问题2解决:
首先需要获取到BottomSheetBehavior然后设置对BottomSheetBehavior.BottomSheetCallback()中的onStateChanged方法进行单独操作,当此时状态newState未BottomSheetBehavior.STATE_HIDDEN时,也就是进入了隐藏状态,执行BottomSheetDialog的dismiss()方法即可。

完整代码如下

public class ZBottomDialog extends BottomSheetDialog {
    private BottomSheetBehavior behavior;

    public ZBottomDialog(@NonNull Context context) {
        super(context, R.style.bottomSheetEdit);
    }

    @Override
    public void setContentView(View view) {
        super.setContentView(view);
        initialize(view);
    }
    private void initialize(final View view) {
        ViewGroup parent = (ViewGroup) view.getParent();
        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
        behavior = (BottomSheetBehavior) params.getBehavior();
        behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    dismiss();
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            }
        });
    }
}

ZBottomSheetAdapter解释说明

本适配器的主要功能是用于底部评论弹窗的图片recyclerview的adapter
该adapter有两种ItemViewType(0:添加图片,1:查看图片)

//对外暴露的监听方法,具体方法见adapter的holder
public void setOnReleaseImageListener(ZBottomSheetHolder.OnReleaseImageListener onReleaseImageListener) {
        this.onReleaseImageListener = onReleaseImageListener;
    }

public interface OnReleaseImageListener {
    //添加图片的点击事件
    void onAddClick();
    //删除图片的点击事件
    void onDelClick(ImageFile imageFile, int position);
    //已经添加的图片点击事件(常用语在底部评论框中点击已经添加的图片大图显示)
    void onClick(int positon);
}

ZBottomSheetAdapter Holder说明

本控件设计之初adapter使用GridLayoutManager spanCount=3,并且具体某个item采用正方形的设计,故需要在holder中进行特殊处理
处理方式:
构造函数中获取到当前item的宽,在加载图片时使用glide对当前图片加载的宽高进行处理

    //获取到当前item的宽,用于将该item设置为正方形
    private int getItemWidth(){
        WindowManager windowManager = (WindowManager) mContext
                .getSystemService(Context.WINDOW_SERVICE);
        return  windowManager.getDefaultDisplay().getWidth();
    }

该holder中的监听方法接口内容:

    public interface OnReleaseImageListener {
        //添加图片的点击事件
        void onAddClick();
        //删除图片的点击事件
        void onDelClick(ImageFile imageFile, int position);
        //已经添加的图片点击事件(常用语在底部评论框中点击已经添加的图片大图显示)
        void onClick(int positon);
    }

    //当前item加载数据,并且glide对图片样式进行处理
    public void setData(ImageFile imageFile) {
        mImageFile = imageFile;
        Glide.with(mContext)
                .load(imageFile.getPath())
                .diskCacheStrategy(DiskCacheStrategy.RESULT)
                .override(mWidth, mWidth)//这里的单位是px
                .into(mCoverView);
    }

总结

在开发过程中很多开源的东西有时候不一定满足我们当前的业务,本控件部分内容前参考了很多人的实现方法然后进行的自定义。
在开源的过程中尽量保证代码的规范以及可读性,便于读者理解。
欢迎大家指点批评~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355