android 自定义登陆对话框基类封装,且随着软键盘的弹起自动移动位置

简介: android 自定义登陆对话框基类封装,且随着软键盘的弹起自动移动位置

像对话框这种常用的组件,用过一次最好做个封装。再次用到时就很简单啦。直接拿过来复用即可。


以下是工作中用到的管理员登录框,由于是双屏异显,在后屏弹出的对话框,没法调用系统软键盘,于是自己实现了个系统软件盘。


但一弹出来软键盘,对话框就被该住了!这怎么破?方法是有的。就是本文介绍的,随着软键盘的弹起自动移动位置的对话框。



先封装实现个baseDialog基础类,把通用的操作封装一下。


package com.newcapec.visitorsystem.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
/**
 * Created by yangyongzhen on 2017/5/12.
 */
public abstract class BaseDialog<T> extends Dialog implements DialogInterface.OnDismissListener, DialogInterface.OnShowListener{
    protected View rootView;
    protected boolean isInit;
    protected Context context;
    protected boolean isFullScreen;
    protected Window window;
    public BaseDialog(Context context) {
        super(context);
        this.context = context;
        window = getWindow();
    }
    public BaseDialog(Context context, boolean isFullScreen) {
        super(context);
        this.context = context;
        this.isFullScreen = isFullScreen;
        window = getWindow();
    }
    public BaseDialog(Context context, int themeResId) {
        super(context, themeResId);
        this.context = context;
        window = getWindow();
       // sysApplication = (App) ((Activity)context).getApplication();
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //hideBottomUIMenu();
       // showBottomUIMenu();
        rootView = getBindingRoot();
        if(rootView!=null){
            setContentView(rootView);
        }else{
            setContentView(getLayoutResid());
        }
        initView();
        initData();
        initEvent();
        setOnDismissListener(this);
        setOnShowListener(this);
    }
    protected int getHeight() {
        return 0;
    }
    protected int getWidth() {
        return 0;
    }
    abstract View getBindingRoot();
    protected void initView() {
        //window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);  //清除灰色背景
    }
    protected int getLayoutResid() {
        return 0;
    }
    protected void initData() {
    }
    protected void initEvent() {
    }
    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        //hideBottomUIMenu();
        Log.i("Dialog", "onDetachedFromWindow");
    }
    @Override
    public void cancel() {
        super.cancel();
    }
    @Override
    public void onDismiss(DialogInterface dialog) {
        doDismiss();
    }
    public void doDismiss() {}
    /**
     * 隐藏虚拟按键:必须放到setContentView前面
     */
    protected void hideBottomUIMenu() {
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) {
            View v = this.getWindow().getDecorView();
            v.setSystemUiVisibility(View.GONE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }
    protected void showBottomUIMenu() {
        //隐藏虚拟按键,并且全屏
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
            View v = this.getWindow().getDecorView();
            v.setSystemUiVisibility(View.VISIBLE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            //for new api versions.
            View decorView =this.getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_IMMERSIVE
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        }
    }
    @Override
    public void onShow(DialogInterface dialog) {
        if(!isInit) {
            isInit = true;
        }
    }
    @Override
    public void show() {
        //focusNotAle(window);
        super.show();
        //hideNavigationBar(window);
        //clearFocusNotAle(window);
    }
}
/**
 * 后屏显示的Dialog的基础类,因为后屏的Dialog的像素密度跟前屏不一样,所以需要改下像素密度才能正常显示
 * 前屏像素密度为1,后屏获取到的为2
 */
public class BackDialog extends BaseDialog {
    private final String TAG = "BackDialog";
    public BackDialog(Context context, int themeResId){
        super(context, themeResId);
        float scale = context.getResources().getDisplayMetrics().density;
        int dp =(int) (48 / scale + 0.5f);
        Log.e(TAG,"dp:"+dp);
    }
    @Override
    View getBindingRoot() {
        //更改Dialog的像素密度
        Utils.setDensity(App.getContext(),context);
        //使背景变暗
//        WindowManager.LayoutParams lp = getWindow().getAttributes();
//        lp.alpha = 0.6f;
//        getWindow().setAttributes(lp);
        //getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        return null;
    }
    /**
     * 禁掉系统软键盘
     */
    public void hideSoftInputMethod(EditText edit) {
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        int currentVersion = android.os.Build.VERSION.SDK_INT;
        String methodName = null;
        if (currentVersion >= 16) {
            // 4.2
            methodName = "setShowSoftInputOnFocus";
        } else if (currentVersion >= 14) {
            // 4.0
            methodName = "setSoftInputShownOnFocus";
        }
        if (methodName == null) {
            edit.setInputType(InputType.TYPE_NULL);
        } else {
            Class<EditText> cls = EditText.class;
            Method setShowSoftInputOnFocus;
            try {
                setShowSoftInputOnFocus = cls.getMethod(methodName, boolean.class);
                setShowSoftInputOnFocus.setAccessible(true);
                setShowSoftInputOnFocus.invoke(edit, false);
            } catch (NoSuchMethodException e) {
                edit.setInputType(InputType.TYPE_NULL);
                e.printStackTrace();
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}


以下是我的LoginDlg继承自基类:


package com.newcapec.visitorsystem.dialog;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.InputType;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import com.newcapec.visitorsystem.R;
import com.newcapec.visitorsystem.diyview.AbcNumberViewBack;
import com.newcapec.visitorsystem.utils.Utils;
public class LoginDlg extends BackDialog {
    private final String TAG = "LoginDlg";
    EditText editInputUsername,editInputPassword;
    AbcNumberViewBack abcNumberView;
    Button btnLogin;
    private OnLoginListener onLoginListener;
    //private DialogLoginBinding loginBinding;
    public LoginDlg(Context context, int themeResId, AbcNumberViewBack abcNumberViewBack){
        super(context, themeResId);
        abcNumberView = abcNumberViewBack;
    }
    @Override
    View getBindingRoot() {
        super.getBindingRoot();
        rootView = LayoutInflater.from(context).inflate(R.layout.dialog_login, null, false);
        //loginBinding = DataBindingUtil.inflate(LayoutInflater.from(context),R.layout.dialog_login,null,false);
        return rootView;
    }
    @Override
    protected void initView() {
        super.initView();
        final Window dialogWindow = this.getWindow();
        WindowManager.LayoutParams lp1 = dialogWindow.getAttributes();
        lp1.width = Utils.dp2px(910); //设置宽度
        lp1.height = Utils.dp2px(660); //设置高度
        //lp1.width = width;
        //lp1.height = height;
        dialogWindow.setAttributes(lp1);
        dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);  //清除灰色背景
        editInputUsername = findViewById(R.id.edit_login_username);
        editInputPassword = findViewById(R.id.edit_login_password);
        btnLogin = findViewById(R.id.btn_login);
    }
    @Override
    protected void initData() {
        super.initData();
        initTouch();
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG,"btn login click:");
                abcNumberView.hideKeyboard();
                resetPosition(0,0,Gravity.CENTER);
                if(onLoginListener != null){
                    onLoginListener.onClickLogin(editInputUsername.getText().toString(),editInputPassword.getText().toString());
                }
                //dismiss();
            }
        });
        //KeyBoardUtils.openKeybord(editInputUsername,context);
    }
    /**
     * 重新设置Dialog的显示位置
     */
    protected void resetPosition(int x,int y,int gravity){
        Window mWindow = getWindow();
        mWindow .setGravity(gravity);
        WindowManager.LayoutParams lp = mWindow.getAttributes();
        lp.x = x; // 新位置X坐标
        lp.y = y; // 新位置Y坐标
        onWindowAttributesChanged(lp);
    }
    @Override public void show(){
        super.show();
    }
    @Override public void dismiss(){
        editInputUsername.setText("");
        editInputPassword.setText("");
        super.dismiss();
    }
    @SuppressLint("ClickableViewAccessibility")
    private void initTouch() {
        //初始化键盘监听
        hideSoftInputMethod(editInputUsername);
        editInputUsername.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                Log.e(TAG, "键盘--------" + event.getAction());
                abcNumberView.setmEdit(editInputUsername);
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (view != null) {
                        resetPosition(0,0,Gravity.TOP);
                        if (!abcNumberView.isShow()) {
                            abcNumberView.showKeyboard();
                        }
                    }
                }
                return false;
            }
        });
        hideSoftInputMethod(editInputPassword);
        editInputPassword.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                Log.e(TAG, "键盘--------" + event.getAction());
                abcNumberView.setmEdit(editInputPassword);
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (view != null) {
                        resetPosition(0,0,Gravity.TOP);
                        if (!abcNumberView.isShow()) {
                            abcNumberView.showKeyboard();
                        }
                    }
                }
                return false;
            }
        });
        abcNumberView.setOkListener(new AbcNumberViewBack.OnOkListener() {
            @Override
            public void onOk(String e) {
                resetPosition(0,0,Gravity.CENTER);
            }
        });
    }
    public interface OnLoginListener {
        void onClickLogin(String name,String pwd);//点击了确认
    }
    public void setOnLoginListener(OnLoginListener onLoginListener) {
        this.onLoginListener = onLoginListener;
    }
}


自动移动位置的秘诀:


 /**
     * 重新设置Dialog的显示位置
     */
    protected void resetPosition(int x,int y,int gravity){
        Window mWindow = getWindow();
        mWindow .setGravity(gravity);
        WindowManager.LayoutParams lp = mWindow.getAttributes();
        lp.x = x; // 新位置X坐标
        lp.y = y; // 新位置Y坐标
        onWindowAttributesChanged(lp);
    }
相关文章
|
3月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
55 1
|
4月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
151 0
|
3月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
3月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
67 5
|
4月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
测试技术 API Android开发
retrofit rxjava android 封装 使用
  本人使用 github 现成封装 modules  rxretrofitlibrary 一步步封装 移步 http://blog.csdn.net/wzgiceman/article/details/51939574 专栏 移步 http://blog.
1150 0
|
2天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
21 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
14天前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
113 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
12天前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
35 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
27天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
76 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android 13 SystemUI 启动流程