当前位置: 首页 > news >正文

关于安卓dialogFragment中,EditText无法删除文字的问题

在这里插入图片描述

背景:

在安卓开发中,使用DialogFragment进行i页面开发,其中有一个EditText,发现可以输入文字,但是无法删除文字

开发环境

win11
jdk11
as

现状与思考

网上回答现状:这个几乎是有点违背常理的,从网上的已有的答案查询,无外乎就是一些说是EditText的焦点问题,一些又说是DialogFragment样式为浮窗的问题,总结一个大类,就是EditText丢失焦点,导致无法删除。

思考:那么,丢了焦点,为什么能够拉起键盘?请回答我?所以如果能拉起键盘,而且能输入,就大概率不是丢了焦点,这是常识性问题。

再延续思考,不是丢焦点,那就是“不响应删除事件”的问题了。

那么响应事件,有两种可能:
(1)父类拦截了删除事件??
(2)EditText类屏蔽了删除事件??
(3)DialogFragment屏蔽了删除事件??

对于(1)和(2),对布局文件进行检查即可。
对于(3),则检查一下DialogFragment中,Dialog有没有重写setOnKeyListener。

通过上述思路,博主是因为下面代码,导致DialogFragment无法删除EditText文字的

            mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {return !mCancelable;if (keyCode == KeyEvent.KEYCODE_BACK) {return !cancelable();}return false;}});

下面放出完整的基类DialogFragment/BottomSheetDialogFragment

BaseDialogFragment类


public abstract class BaseDialogFragment extends DialogFragment {private int DEFAULT_WIDTH = WindowManager.LayoutParams.MATCH_PARENT;//宽private int DEFAULT_HEIGHT = WindowManager.LayoutParams.MATCH_PARENT;//高private int DEFAULT_GRAVITY = Gravity.BOTTOM;//位置//外部设置能否取消点击private boolean mCancelable = true;private BaseDialogFragmentLifeListener mListener;private boolean hadShowTAG = false;public BaseDialogFragment() {}public BaseDialogFragment(BaseDialogFragmentLifeListener listener) {this.mListener = listener;}protected BaseDialogFragmentLifeListener getListener() {return mListener;}@Overridepublic void onResume() {super.onResume();if (!hadShowTAG) {hadShowTAG = true;firstShow();}}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (immerseStyle()) {setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogFragmentImmerse);}}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View mView = inflater.inflate(getLayoutId(), container, false);initViews(mView);if (this.mListener != null) {this.mListener.show();}return mView;}@Overridepublic void onDestroyView() {if (this.mListener != null) {this.mListener.dismiss();}this.mListener = null;releaseResource();super.onDestroyView();}@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {mCancelable = cancelable();Dialog mDialog = super.onCreateDialog(savedInstanceState);if (null != mDialog) {//初始化mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);mDialog.setCanceledOnTouchOutside(canceledOnTouchOutside());mDialog.setCancelable(mCancelable);Window window = mDialog.getWindow();if (null != window) {window.getDecorView().setPadding(0, 0, 0, 0);window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));window.getDecorView().clearFocus();WindowManager.LayoutParams lp = window.getAttributes();lp.width = defWidth();lp.height = defHeight();lp.gravity = DEFAULT_GRAVITY;lp.windowAnimations = android.R.style.Animation_InputMethod;window.setAttributes(lp);window.setDimAmount(dimAmount());}mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {return !cancelable();}return false;}});}return mDialog;}@Overridepublic void onStart() {super.onStart();initImmerseSystemBar();}@Overridepublic void onDismiss(@NonNull DialogInterface dialog) {super.onDismiss(dialog);dismissDialog();}protected void setCancelAble(boolean cancelAble) {mCancelable = cancelAble;Dialog dialog = getDialog();if (dialog != null) {dialog.setCancelable(mCancelable);dialog.setCanceledOnTouchOutside(mCancelable);}}/*** 主线程执行*/protected void runInUI(Runnable runnable) {if (runnable == null || getActivity() == null) {return;}getActivity().runOnUiThread(runnable);}@Overridepublic void dismiss() {super.dismiss();dismissDialog();}@Deprecatedprotected void dismissDialog() {}protected float dimAmount() {return 0.6f;}protected int defWidth() {return DEFAULT_WIDTH;}protected int defHeight() {return DEFAULT_HEIGHT;}/*** 设置位置** @param gravity*/public void setGravity(int gravity) {DEFAULT_GRAVITY = gravity;}/*** 设置宽** @param width*/public void setWidth(int width) {DEFAULT_WIDTH = width;}/*** 设置高** @param height*/public void setHeight(int height) {DEFAULT_HEIGHT = height;}/*** 设置点击返回按钮是否可取消*/public boolean cancelable() {return true;}/*** 设置点击外部是否可取消*/public boolean canceledOnTouchOutside() {return true;}/*** 设置布局** @return*/protected abstract int getLayoutId();/*** 初始化Views** @param v*/protected abstract void initViews(@NonNull View v);//全屏相关------------------------------------------------------------------/*** 沉浸样式*/protected boolean immerseStyle() {return false;}/*** 全屏状态下,底部导航栏颜色*/protected int immerseNavigationBarColor() {return Color.WHITE;}protected int immerseStatusBarColor() {return Color.WHITE;}private void initImmerseSystemBar() {if (immerseStyle()) {Window window = getDialog() != null ? getDialog().getWindow() : null;if (window != null) {// 设置导航栏颜色window.setNavigationBarColor(immerseNavigationBarColor());window.setStatusBarColor(immerseStatusBarColor());// 设置导航栏图标颜色为深色(适用于浅色背景)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {View decorView = window.getDecorView();int flags = decorView.getSystemUiVisibility();flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;decorView.setSystemUiVisibility(flags);}}}}//rxjava release----------------------------private CompositeDisposable mDisposables = new CompositeDisposable();private void addObserver(DisposableObserver<?> disposableObserver) {mDisposables.add(disposableObserver);}private void removeObserver(DisposableObserver<?> disposableObserver) {if (mDisposables == null || disposableObserver == null) {return;}mDisposables.remove(disposableObserver);}private void clearObserver() {if (mDisposables != null) {mDisposables.clear();}}public abstract class BaseSafeObserver<T> extends DisposableObserver<T> {@Overrideprotected void onStart() {super.onStart();addObserver(this);}@Overridepublic void onNext(@NonNull T t) {}@Overridepublic void onError(@NonNull Throwable e) {removeObserver(this);}@Overridepublic void onComplete() {removeObserver(this);}}public void releaseResource() {clearObserver();}public <T> void addRequest(Flowable<T> flowable, final OnResultListener<T> onResultListener) {Disposable disposable = flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<T>() {@Overridepublic void accept(T t) throws Exception {onResultListener.onResult(t);onResultListener.onFinish();}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) {throwable.printStackTrace();onResultListener.onError(throwable);onResultListener.onFinish();}});mDisposables.add(disposable);}public interface OnResultListener<T> {void onResult(T t);void onError(Throwable t);void onFinish();}//rxjava release----------------------------protected void firstShow() {}
}

BaseBottomDialogFragment类


public abstract class BaseBottomDialogFragment extends BottomSheetDialogFragment {private int DEFAULT_WIDTH = WindowManager.LayoutParams.MATCH_PARENT;//宽private int DEFAULT_HEIGHT = WindowManager.LayoutParams.MATCH_PARENT;//高private int DEFAULT_GRAVITY = Gravity.BOTTOM;//位置private boolean hadShowTAG = false;private BottomSheetBehavior<FrameLayout> bottomSheetBehavior;private BaseDialogFragmentLifeListener mListener;public BaseBottomDialogFragment() {}public BaseBottomDialogFragment(BaseDialogFragmentLifeListener listener) {this.mListener = listener;}@Overridepublic void onResume() {super.onResume();if (!hadShowTAG) {hadShowTAG = true;firstShow();}}protected BaseDialogFragmentLifeListener getListener() {return mListener;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (fullScreenStyle()) {setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogFragmentImmerse);}}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View mView = inflater.inflate(getLayoutId(), container, false);if (getDialog() != null && getDialog().getWindow() != null) {getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);}initViews(mView);if (this.mListener != null) {this.mListener.show();}return mView;}@Overridepublic void onDestroyView() {if (this.mListener != null) {this.mListener.dismiss();}this.mListener = null;releaseResource();super.onDestroyView();}@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {BottomSheetDialog mDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);if (null != mDialog) {//初始化mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);mDialog.setCanceledOnTouchOutside(canceledOnTouchOutside());mDialog.setCancelable(cancelable());Window window = mDialog.getWindow();if (null != window) {window.getDecorView().setPadding(0, 0, 0, 0);window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));WindowManager.LayoutParams lp = window.getAttributes();lp.width = defWidth();lp.height = defHeight();lp.gravity = DEFAULT_GRAVITY;lp.windowAnimations = android.R.style.Animation_InputMethod;window.setAttributes(lp);window.setDimAmount(dimAmount());}mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {return !cancelable();}return false;}});}return mDialog;}@Overridepublic void onStart() {super.onStart();initSlide();initImmerseSystemBar();}@Overridepublic void onDismiss(@NonNull DialogInterface dialog) {super.onDismiss(dialog);dismissDialog();LogUtils.d("bottom sheet dialog fragment: onDismiss");}/*** 主线程执行*/protected void runInUI(Runnable runnable) {if (runnable == null || getActivity() == null) {return;}getActivity().runOnUiThread(runnable);}/*** 初始化滑动交互*/private void initSlide() {try {if (getDialog() != null && getDialog() instanceof BottomSheetDialog) {int peekHeight = getPeekHeight();BottomSheetDialog dialog = (BottomSheetDialog) getDialog();//把windows的默认背景颜色去掉,不然圆角显示不见dialog.getWindow().findViewById(R.id.design_bottom_sheet).setBackground(new ColorDrawable(Color.TRANSPARENT));//获取dialog的根部局FrameLayout bottomSheet = dialog.getDelegate().findViewById(R.id.design_bottom_sheet);//获取根部局的LayoutParams对象CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) bottomSheet.getLayoutParams();layoutParams.height = peekHeight;//修改弹窗的最大高度,不允许上滑(默认可以上滑)bottomSheet.setLayoutParams(layoutParams);bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);//peekHeight即弹窗的最大高度bottomSheetBehavior.setPeekHeight(peekHeight);//初始为展开状态bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);//能否滑动的时候隐藏bottomSheetBehavior.setHideable(hideAble());}} catch (Exception e) {e.printStackTrace();}}@Overridepublic void dismiss() {super.dismiss();dismissDialog();LogUtils.d("bottom sheet dialog fragment: dismiss");}@Deprecatedprotected void dismissDialog() {}@Overridepublic void show(@NonNull FragmentManager manager, @Nullable String tag) {super.show(manager, tag);}/*** 弹窗高度* 子类可重写该方法返回peekHeight** @return height*/protected int getPeekHeight() {return getResources().getDisplayMetrics().heightPixels;}protected float dimAmount() {return 0.6f;}protected int defWidth() {return DEFAULT_WIDTH;}protected int defHeight() {return DEFAULT_HEIGHT;}/*** 设置位置** @param gravity*/public void setGravity(int gravity) {DEFAULT_GRAVITY = gravity;}/*** 设置宽** @param width*/public void setWidth(int width) {DEFAULT_WIDTH = width;}/*** 设置高** @param height*/public void setHeight(int height) {DEFAULT_HEIGHT = height;}/*** 设置点击返回按钮是否可取消*/public boolean cancelable() {return true;}/*** 设置点击外部是否可取消*/public boolean canceledOnTouchOutside() {return true;}public boolean hideAble() {return true;}/*** 设置布局** @return*/protected abstract int getLayoutId();/*** 初始化Views** @param v*/protected abstract void initViews(@NonNull View v);//全屏相关------------------------------------------------------------------/*** 全屏开光*/protected boolean fullScreenStyle() {return false;}/*** 全屏状态下,底部导航栏颜色*/protected int immerseNavigationBarColor() {return Color.WHITE;}protected int immerseStatusBarColor() {return Color.WHITE;}private void initImmerseSystemBar() {if (fullScreenStyle()) {Window window = getDialog() != null ? getDialog().getWindow() : null;if (window != null) {// 设置导航栏颜色window.setNavigationBarColor(immerseNavigationBarColor());window.setStatusBarColor(immerseStatusBarColor());// 设置导航栏图标颜色为深色(适用于浅色背景)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {View decorView = window.getDecorView();int flags = decorView.getSystemUiVisibility();flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;decorView.setSystemUiVisibility(flags);}}}}//rxjava release----------------------------private CompositeDisposable mDisposables = new CompositeDisposable();private void addObserver(DisposableObserver<?> disposableObserver) {mDisposables.add(disposableObserver);}private void removeObserver(DisposableObserver<?> disposableObserver) {if (mDisposables == null || disposableObserver == null) {return;}mDisposables.remove(disposableObserver);}private void clearObserver() {if (mDisposables != null) {mDisposables.clear();}}public abstract class BaseSafeObserver<T> extends DisposableObserver<T> {@Overrideprotected void onStart() {super.onStart();addObserver(this);}@Overridepublic void onNext(@NonNull T t) {}@Overridepublic void onError(@NonNull Throwable e) {removeObserver(this);}@Overridepublic void onComplete() {removeObserver(this);}}public void releaseResource() {clearObserver();}public <T> void addRequest(Flowable<T> flowable, final OnResultListener<T> onResultListener) {Disposable disposable = flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<T>() {@Overridepublic void accept(T t) throws Exception {onResultListener.onResult(t);onResultListener.onFinish();}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) {throwable.printStackTrace();onResultListener.onError(throwable);onResultListener.onFinish();}});mDisposables.add(disposable);}public interface OnResultListener<T> {void onResult(T t);void onError(Throwable t);void onFinish();}//rxjava release----------------------------protected void firstShow() {}}

相关的样式:

    <style name="DialogFragmentImmerse" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowIsFloating">false</item> <!-- 核心:非浮动窗口 -->
<!--        <item name="android:windowFullscreen">true</item>--><item name="android:windowDrawsSystemBarBackgrounds">true</item><item name="android:windowTranslucentNavigation">false</item><item name="android:windowTranslucentStatus">false</item><item name="android:windowBackground">@android:color/transparent</item><item name="android:backgroundDimEnabled">true</item></style>



代码说明

上述代码中,有这样一个函数
在这里插入图片描述
这个方法,是用来实现DialogFragment的沉浸样式的,对于DialogFragment的全屏样式,非常简单,这里不再一一叙述,重点是沉浸样式。
普通的DialogFragment实现,状态栏和内容区域有明显的色差,这个时候就需要设置沉浸状态栏,让色差过度更加自然,这里的

                    View decorView = window.getDecorView();int flags = decorView.getSystemUiVisibility();flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;decorView.setSystemUiVisibility(flags);

就是核心代码。而对于

                window.setNavigationBarColor(immerseNavigationBarColor());window.setStatusBarColor(immerseStatusBarColor());

则是设置底部导航栏和顶部状态栏的两个系统API,没什么好说的。

简单用法

通过字类继承这两个基类实现即可。若需要自定义沉浸状态栏,则重写这几个代码即可:

    @Overrideprotected boolean immerseStyle() {return true;}@Overridepublic boolean cancelable() {return false;}@Overrideprotected float dimAmount() {return 0f;}@Overrideprotected int immerseStatusBarColor() {return Color.parseColor("#80060606");}@Overrideprotected int immerseNavigationBarColor() {return Color.parseColor("#80060606");}

若是想基于上述基类,扩展DataBinding,则重写方法onCreateView即可

通过DataBindingUtil.inflate创建一个databinding对象,然后api调用getRoot()即可返回上级一个View。这样就能实现了,核心截图和代码如下:
在这里插入图片描述

public abstract class BaseDBDialogFragment<D extends ViewDataBinding> extends BaseDialogFragment {protected D binding;public D getBinding() {return binding;}public BaseDBDialogFragment() {}public BaseDBDialogFragment(BaseDialogFragmentLifeListener listener) {super(listener);}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);binding.setLifecycleOwner(this);initViews(binding.getRoot());if (getListener() != null) {getListener().show();}return binding.getRoot();}
}

更多日常信息,可focus我gzh。 老李up野

that’s all-------------------------------------------------------------------------------------------------------------

相关文章:

  • Android NTP自动同步时间机制
  • 展开说说Android之Glide详解_使用篇
  • DRG支付场景模拟器扩展分析:技术实现与应用价值
  • 算法导论第三章:数据结构艺术与高效实现
  • 为什么TCP有粘包问题,而UDP没有
  • 前端导出PDF(适配ios Safari浏览器)
  • 力扣HOT100之技巧:136. 只出现一次的数字
  • opencl的简单介绍以及c++实例
  • 爱普生FC-135R晶振在广域网LoRa设备中的应用
  • openEuler 虚拟机中 Shell 脚本实现自动化备份与清理实践
  • Tomcat线程模型
  • 单链表经典算法
  • nt!CcGetDirtyPages函数分析
  • 软件测试相关问题
  • 蓝牙无线串口入门使用教程(以大夏龙雀 WF24 和 BT36 为例)
  • PCI总线概述
  • 【开源工具】:基于PyQt5的智能网络驱动器映射工具开发全流程(附源码)
  • Java 大视界——Java大数据在智能安防视频监控中的异常事件快速响应与处理机制
  • 动态规划2——路径动态规划
  • 【消息队列】——如何实现消息保序
  • 专业网站制作公司排行/网站整合营销推广
  • 公司网站现状/北京百度关键词排名
  • wordpress和vue/seo首页优化
  • 简述网站开发的流程/进入百度
  • 网站建设管理概述/网站收录查询
  • 申报网站/游戏优化是什么意思?