FRDialog

Introduction: 用 Builder 模式重新打造一个 dialog
More: Author   ReportBugs   
Tags:

用 Builder 模式重新打造一个 dialog,案例中有两种 Builder,分别是 CommonBuilder 和 MDBuilder,如果还想实现其他的通用,继承自 FRBaseDialogBuilder 即可。

jcenter Author Api

注意

从 2019.05.23 日开始,该库升级为支持 androidx,如果你的项目还没有升级支持的话,那么只能使用 1.0.6 之前的版本。

1、添加依赖

Gradle:

repositories {
    jcenter()
}

dependencies {
    //lastVersion 请参照上述版本号
    compile 'com.jack.frdialog:FRDialog:latestVersion'
}

2、使用案例

2.1、普通 Dialog

private void showCommonDialog() {
    final FRDialog dialog = new FRDialog.CommonBuilder(this)
            .setContentView(R.layout.dialog_common)
            .setText(R.id.dcu_tv_cancel, "否")
            .setText(R.id.dcu_tv_confirm, "是")
            .setText(R.id.dcu_tv_title, "温馨提示")
            .setText(R.id.dcu_tv_content, "1.文字文字我是文字文字文字我是文字文字文字我是文字!\n2.文字文字文字文字文字\n3.文字文字文字文字文字")
            .setDefaultAnim()
            .show();

    dialog.setText(R.id.dcu_tv_confirm, "确定");

    dialog.setOnClickListener(R.id.dcu_tv_cancel, new FRDialogClickListener() {
        @Override
        public boolean onDialogClick(View view) {
            Toast.makeText(MainActivity.this, "点击了否", Toast.LENGTH_SHORT).show();
            return true;
        }
    });

    dialog.setOnClickListener(R.id.dcu_tv_confirm, new FRDialogClickListener() {
        @Override
        public boolean onDialogClick(View v) {
            Toast.makeText(MainActivity.this, "点击了是", Toast.LENGTH_SHORT).show();
            return false;
        }
    });
}

普通 dialog

2.2、MaterialDesign Dialog

private void showMDDialog() {
    FRDialog dialog = new FRDialog.MDBuilder(this)
                    .setMessage("1.文字文字我是文字文字!\n2.文字文字文字文字文字\n3.文字文字文字文字文字")
                    .setTitle("温馨提示")
                    .setNegativeContentAndListener("否", null)
                    .setNegativeTextColor(ContextCompat.getColor(this,R.color.c999999))
                    .setPositiveTextColor(ContextCompat.getColor(this,R.color.colorPrimary))
                    .setPositiveContentAndListener("是", new FRDialogClickListener() {
                        @Override
                        public boolean onDialogClick(View view) {
                            return true;
                        }
                    }).show();
}

MD 效果的 dialog

2.3、从底部弹出来的 Dialog

FRDialog dialog = new FRDialog.CommonBuilder(this)
  .setContentView(R.layout.dialog_from_bottom)
  .setFullWidth()
  .setFromBottom()
  .show();

从底部弹出的 dialog

3、特殊设置:

继承所有 dialog 的设置,同时还可以自定义以下设置

//设置宽度全屏
dialog.setFullWidth()

//设置从底部弹出
dialog.setFromBottom()

//设置弹出动画
dialog.setAnimation(int anim)

2018.5.24 日更新

将 mWidth 改成 mWidthRatio,不让用户设置一个具体的宽度,而是让用户去设置一个宽度比例,然后通过改变 window 的 LayoutParams 来设置 dialog 的宽高:

WindowManager.LayoutParams lp = window.getAttributes();
lp.width = (int) (baseBuilder.mContext.getResources().getDisplayMetrics().widthPixels * baseBuilder.mWidthRatio);
lp.height = baseBuilder.mHeight;
window.setAttributes(lp);

用法还是和之前一样:

dialog.setWidthRatio(0——1)  默认是 0.9

2018.7.19 日更新

新增点击 dialog 中非 EditText 区域隐藏软键盘

重写 dispatchTouchEvent 方法进行拦截:

/**
 * 点击 dialog 中除 EditText 以外的区域隐藏软键盘
 *
 * @param ev
 * @return
 */
@Override
public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
    FRInputMethodManager.autoHideSoftInput(this, ev);
    return super.dispatchTouchEvent(ev);
}

//核心方法
public static boolean isAutoHideSoftInput(View view, MotionEvent event) {
    if (event.getAction() != MotionEvent.ACTION_DOWN) {
        return false;
    }

    if (!(view instanceof EditText)) {
        return false;
    }

    float x = event.getX();
    float y = event.getY();

    int[] location = {0, 0};
    view.getLocationInWindow(location);
    int left = location[0];
    int top = location[1];
    int bottom = top + view.getHeight();
    int right = left + view.getWidth();
    if (left <= x && x < right && top <= y && y < bottom) {
        // 点击事件在 EditText 的区域里
        return false;
    }

    return true;
}

用法不变。

2018.9.11 日更新

新增 recyclerview 样式的 dialogBuilder

具体功能有:

  • 设置一个列表布局,只需要传一个 adapter 就好了

  • 可以给列表添加头部和底部

  • 可以给 dialog 添加头部和底部

用法:

    private void showRecyclerViewDialog() {
        List<Object> mDataList = new ArrayList<>();
        mDataList.add(new TestDataBean("张三", "2018-09-11 14:00"));
        mDataList.add(new TestDataBean("李四", "2018-09-11 11:00"));
        mDataList.add(new TestDataBean("王五", "2018-09-11 12:00"));
        mDataList.add(new TestDataBean("李四", "2018-09-11 13:00"));
        mDataList.add(new TestDataBean("张三", "2018-09-11 16:00"));
        mDataList.add(new TestDataBean("王五", "2018-09-11 15:00"));


        final FRDialog dialog = new FRDialog.RecyclerViewBuilder(this)
                .setLayoutManager(new LinearLayoutManager(MainActivity.this))
                .setAdapter(new FRBaseDialogAdapter<TestDataBean>(MainActivity.this) {

                    @Override
                    protected int getLayoutRes() {
                        return R.layout.item_test;
                    }

                    @Override
                    protected void convert(FRBaseDialogViewHolder holder, TestDataBean dataBean, int position, List<Object> payloads) {
                        holder.setImageResource(R.id.it_iv_image, R.mipmap.ic_launcher_round);
                        holder.setText(R.id.it_tv_title, dataBean.getName());
                        holder.setText(R.id.it_tv_time, dataBean.getTime());
                    }
                }).setDataList(mDataList)
                .setHeightRatio(0.5)
                .addRecyclerViewHeader(R.layout.layout_header)
                .addDialogFooter(R.layout.layout_footer)
                .setOnClickListener(R.id.lf_tv_cancel, view -> true)
                .setOnClickListener(R.id.lf_tv_confirm, view -> {
                    Toast.makeText(MainActivity.this, "点击了确定", Toast.LENGTH_SHORT).show();
                    return false;
                })
                .show();
    }

详细可以参照 demo 中的。

2018.11.14 日更新

新增适配在 Service 中国弹出 dialog

首先 Android5.x 以上的版本都需要适配,8.x 版本的需要单独设置 window 的 type 类型,8.x 以下版本,还需要申请悬浮窗的权限,因为我们是将 dialog 作为一个悬浮窗来弹出来

dialog 中:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    Objects.requireNonNull(window).setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Objects.requireNonNull(window).setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
    openOverlaySettings();
} else {
    startService(new Intent(this, DialogService.class));
}

private void openOverlaySettings() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        try {
            //打开权限申请页面
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, RC_OVERLAY);
        } catch (ActivityNotFoundException e) {
            Log.e("TAG", "ActivityNotFoundException--->" + e.getMessage());
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case RC_OVERLAY:
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                // 判断当前有没有授权成功
                if (Settings.canDrawOverlays(this)) {
                    startService(new Intent(this, DialogService.class));
                }
            }
        break;
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    stopService(new Intent(this, DialogService.class));
}

2018.12.29 日更新

新增 dialog 的偏移量,可以自定义 dialog 的显示位置

FRDialog dialog = new FRDialog.CommonBuilder(this, R.style.transparent_dialog)
                .setContentView(R.layout.dialog_offsetx)
                .setGravity(Gravity.LEFT | Gravity.TOP)
                .setOnClickListener(R.id.do_tv_praised, view -> {
                    Toast.makeText(DialogOffsetActivity.this, "赞", Toast.LENGTH_SHORT).show();
                    return true;
                })
                .setOnClickListener(R.id.do_tv_comment, view -> {
                    Toast.makeText(DialogOffsetActivity.this, "评论", Toast.LENGTH_SHORT).show();
                    return true;
                })
                .setOffsetX(dp2px(100))
                .setOffsetY(dp2px(51))
                .show();

2019.05.23 日更新

此次更新主要是升级到 androidx,然后将内部使用的三方库(support 包和 recyclerview 包)设置成 implemention,外部不可访问,用法不变

公众号

欢迎关注我的个人公众号【IT 先森养成记】,专注大前端技术分享,包含 Android,Java 基础,Kotlin,HTML,CSS,JS 等技术;在这里你能得到的不止是技术上的提升,还有一些学习经验以及志同道合的朋友,赶快加入我们,一起学习,一起进化吧!!!

公众号:IT 先森养成记

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools