博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NewBuiltBottomSheetDialog【新建底部对话框】
阅读量:6924 次
发布时间:2019-06-27

本文共 17210 字,大约阅读时间需要 57 分钟。

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

演示在底部选项卡上方弹出底部对话框效果。

效果图

代码分析

NewBuiltBottomSheetDialog继承BottomSheetDialog;

适配华为手机手动隐藏虚拟导航栏,监听屏幕高度变化;

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

在APP中的bundle.gradle文件中添加以下代码,引入design【版本号跟appcompat-v7的保持一致】

apply plugin: 'com.android.application'android {    compileSdkVersion 27    defaultConfig {        applicationId "com.why.project.newbuiltbottomsheetdialogdemo"        minSdkVersion 16        targetSdkVersion 27        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'com.android.support:appcompat-v7:27.1.1'    implementation 'com.android.support.constraint:constraint-layout:1.1.0'    testImplementation 'junit:junit:4.12'    androidTestImplementation 'com.android.support.test:runner:1.0.2'    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'    //BottomSheetDialog    compile "com.android.support:design:27.1.1"}

首页界面底部选项卡区域布局文件

需要指定底部选项卡区域的id值:@+id/bottom_layout,用于在监听屏幕高度变化中获取屏幕的实际高度值;

需要制定底部选项卡区域高度值:@dimen/tab_bottom_height,用于在监听屏幕高度变化中获取屏幕的实际高度值;

首页界面监听屏幕高度变化,获取屏幕实际高度值的方法

声明一个变量,存储屏幕的实际高度值,并传入NewBuiltBottomSheetDialog中。

package com.why.project.newbuiltbottomsheetdialogdemo;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewTreeObserver;import android.widget.Button;import android.widget.Toast;import com.why.project.newbuiltbottomsheetdialogdemo.dialog.NewBuiltBottomSheetDialog;public class MainActivity extends AppCompatActivity {    private Button btn_add;    private int displayHeight = 0;//屏幕显示的高度值(不包括虚拟导航栏的高度)    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initViews();        initEvents();    }    private void initViews() {        btn_add = findViewById(R.id.btn_add);    }    private void initEvents() {        //监听屏幕高度变化        View rootView = this.getWindow().getDecorView();        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {            @Override            public void onGlobalLayout() {                //https://blog.csdn.net/u013872857/article/details/53750682                int[] loc = new int[2];                findViewById(R.id.bottom_layout).getLocationOnScreen(loc);                displayHeight = loc[1] + getResources().getDimensionPixelSize(R.dimen.tab_bottom_height);//底部区域+底部的高度值=显示区域的高度值            }        });        btn_add.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                NewBuiltBottomSheetDialog bottomSheetDialog = new NewBuiltBottomSheetDialog(MainActivity.this,displayHeight);                bottomSheetDialog.setOnCustomButtonClickListener(new NewBuiltBottomSheetDialog.OnCustomButtonClickListener() {                    @Override                    public void onAddNoteButtonClick() {                        //打开新建笔记界面                        Toast.makeText(MainActivity.this,"新建笔记",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddFileButtonClick() {                        //打开新建文件界面                        Toast.makeText(MainActivity.this,"新建文件",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddPhotoButtonClick() {                        //打开新建图片界面                        Toast.makeText(MainActivity.this,"新建图片",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddVideoButtonClick() {                        //打开新建视频界面                        Toast.makeText(MainActivity.this,"新建视频",Toast.LENGTH_SHORT).show();                    }                });                bottomSheetDialog.show();            }        });    }}

打开的新建底部对话框布局文件

关键在于需要指定内边距的下方值android:paddingBottom="@dimen/tab_bottom_height",高度值就是首页的底部选项卡区域的高度值。

打开的新建底部对话框

package com.why.project.newbuiltbottomsheetdialogdemo.dialog;import android.app.Activity;import android.content.Context;import android.content.ContextWrapper;import android.content.res.Resources;import android.os.Build;import android.os.Bundle;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.design.widget.BottomSheetDialog;import android.util.DisplayMetrics;import android.view.Display;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.TextView;import com.why.project.newbuiltbottomsheetdialogdemo.R;import java.lang.reflect.Method;/** * Created by HaiyuKing * Used */public class NewBuiltBottomSheetDialog extends BottomSheetDialog {    private static final String TAG = NewBuiltBottomSheetDialog.class.getSimpleName();    private Context mContext;    private int displayHeight_build;//屏幕显示的高度值,从activity中传入,用于判断是否存在虚拟导航栏    private TextView tv_addNote;    private TextView tv_addFile;    private TextView tv_addPhoto;    private TextView tv_addVideo;    public NewBuiltBottomSheetDialog(@NonNull Context context, int displayHeight) {        super(context);        mContext = context;        this.displayHeight_build = displayHeight;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.dialog_bottomsheet_new_built);        //可以变相实现底部外边距效果        int screenHeight = getScreenHeight(scanForActivity(mContext));        int statusBarHeight = getStatusBarHeight(getContext());        int navigationBarHeight = getNavigationBarHeight(getContext());//底部虚拟导航高度        //如果传入的displayHeight_build == 0,那么就使用默认的方法(存在的问题是,显示虚拟导航栏打开APP后,使用过程中隐藏虚拟导航栏,再打开对话框的时候,显示的位置不正确)        int dialogHeight = screenHeight - navigationBarHeight - dip2px(mContext,0);//dip2px(mContext,0)预留在这里,如果以后想要调整距离的话        if(displayHeight_build > 0){            dialogHeight = displayHeight_build - navigationBarHeight - dip2px(mContext,0);//dip2px(mContext,0)预留在这里,如果以后想要调整距离的话        }//        getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, dialogHeight == 0 ? ViewGroup.LayoutParams.MATCH_PARENT : dialogHeight);        getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);//红米6pro适配        //设置透明        getWindow().findViewById(R.id.design_bottom_sheet).setBackgroundResource(android.R.color.transparent);        initViews();        initEvents();    }    /**获取实际屏幕高度,不包括虚拟功能高度*/    private int getScreenHeight(Activity activity) {        DisplayMetrics displaymetrics = new DisplayMetrics();        Display d = activity.getWindowManager().getDefaultDisplay();        d.getMetrics(displaymetrics);        return displaymetrics.heightPixels;    }    /**获取状态栏高度值*/    private int getStatusBarHeight(Context context) {        int statusBarHeight = 0;        Resources res = context.getResources();        int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");        if (resourceId > 0) {            statusBarHeight = res.getDimensionPixelSize(resourceId);        }        return statusBarHeight;    }    /**     * 获取底部虚拟导航栏高度     */    public int getNavigationBarHeight(Context activity) {        boolean hasNavigationBar = navigationBarExist(scanForActivity(activity)) && !vivoNavigationGestureEnabled(activity);        if (!hasNavigationBar) {
//如果不含有虚拟导航栏,则返回高度值0 return 0; } Resources resources = activity.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); //获取NavigationBar的高度 int height = resources.getDimensionPixelSize(resourceId); return height; } /*========================================方法1======================================================*/ /** * 通过获取不同状态的屏幕高度对比判断是否有NavigationBar * https://blog.csdn.net/u010042660/article/details/51491572 * https://blog.csdn.net/android_zhengyongbo/article/details/68941464*/ public boolean navigationBarExist(Activity activity) { WindowManager windowManager = activity.getWindowManager(); Display d = windowManager.getDefaultDisplay(); DisplayMetrics realDisplayMetrics = new DisplayMetrics(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { d.getRealMetrics(realDisplayMetrics); } int realHeight = realDisplayMetrics.heightPixels; int realWidth = realDisplayMetrics.widthPixels; DisplayMetrics displayMetrics = new DisplayMetrics(); d.getMetrics(displayMetrics); int displayHeight = displayMetrics.heightPixels; int displayWidth = displayMetrics.widthPixels; if(this.displayHeight_build > 0){ displayHeight = displayHeight_build; } return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0; } /*========================================方法2======================================================*/ /** * 检测是否有底部虚拟导航栏【有点儿问题,当隐藏虚拟导航栏后,打开APP,仍然判断显示了虚拟导航栏】 * @param context * @return */ public boolean checkDeviceHasNavigationBar(Context context) { boolean hasNavigationBar = false; Resources rs = context.getResources(); int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { hasNavigationBar = rs.getBoolean(id); } try { Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); Method m = systemPropertiesClass.getMethod("get", String.class); String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { hasNavigationBar = false; } else if ("0".equals(navBarOverride)) { hasNavigationBar = true; } } catch (Exception e) { } return hasNavigationBar; } /** * 获取vivo手机设置中的"navigation_gesture_on"值,判断当前系统是使用导航键还是手势导航操作 * @param context app Context * @return false 表示使用的是虚拟导航键(NavigationBar), true 表示使用的是手势, 默认是false * https://blog.csdn.net/weelyy/article/details/79284332#更换部分被拉伸的图片资源文件 * 由于全面屏手机都没有底部的Home,Back等实体按键,因此,大多数全面屏手机都是支持虚拟导航键,即通过上面的方法checkDeviceHasNavigationBar获取的返回值都是true。 */ public boolean vivoNavigationGestureEnabled(Context context) { int val = Settings.Secure.getInt(context.getContentResolver(), "navigation_gesture_on", 0); return val != 0; } /**解决java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to android.app.Activity问题 * https://blog.csdn.net/yaphetzhao/article/details/49639097*/ private Activity scanForActivity(Context cont) { if (cont == null) return null; else if (cont instanceof Activity) return (Activity)cont; else if (cont instanceof ContextWrapper) return scanForActivity(((ContextWrapper)cont).getBaseContext()); return null; } /** * 获取dp的px值*/ public int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } private void initViews() { tv_addNote = (TextView) findViewById(R.id.tv_addNote); tv_addFile = (TextView) findViewById(R.id.tv_addFile); tv_addPhoto = (TextView) findViewById(R.id.tv_addPhoto); tv_addVideo = (TextView) findViewById(R.id.tv_addVideo); } private void initEvents() { tv_addNote.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mOnCustomButtonClickListener != null){ mOnCustomButtonClickListener.onAddNoteButtonClick(); } dismiss(); } }); tv_addFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mOnCustomButtonClickListener != null){ mOnCustomButtonClickListener.onAddFileButtonClick(); } dismiss(); } }); tv_addPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mOnCustomButtonClickListener != null){ mOnCustomButtonClickListener.onAddPhotoButtonClick(); } dismiss(); } }); tv_addVideo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mOnCustomButtonClickListener != null){ mOnCustomButtonClickListener.onAddVideoButtonClick(); } dismiss(); } }); } public static abstract interface OnCustomButtonClickListener { //新建笔记按钮的点击事件接口 public abstract void onAddNoteButtonClick(); //新建文件按钮的点击事件接口 public abstract void onAddFileButtonClick(); //新建图集按钮的点击事件接口 public abstract void onAddPhotoButtonClick(); //新建视频按钮的点击事件接口 public abstract void onAddVideoButtonClick(); } private OnCustomButtonClickListener mOnCustomButtonClickListener; public void setOnCustomButtonClickListener(OnCustomButtonClickListener mOnCustomButtonClickListener) { this.mOnCustomButtonClickListener = mOnCustomButtonClickListener; }}

首页底部选项卡的高度值

52dp

三、使用方法

package com.why.project.newbuiltbottomsheetdialogdemo;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewTreeObserver;import android.widget.Button;import android.widget.Toast;import com.why.project.newbuiltbottomsheetdialogdemo.dialog.NewBuiltBottomSheetDialog;public class MainActivity extends AppCompatActivity {    private Button btn_add;    private int displayHeight = 0;//屏幕显示的高度值(不包括虚拟导航栏的高度)    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initViews();        initEvents();    }    private void initViews() {        btn_add = findViewById(R.id.btn_add);    }    private void initEvents() {        //监听屏幕高度变化        View rootView = this.getWindow().getDecorView();        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {            @Override            public void onGlobalLayout() {                //https://blog.csdn.net/u013872857/article/details/53750682                int[] loc = new int[2];                findViewById(R.id.bottom_layout).getLocationOnScreen(loc);                displayHeight = loc[1] + getResources().getDimensionPixelSize(R.dimen.tab_bottom_height);//底部区域+底部的高度值=显示区域的高度值            }        });        btn_add.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                NewBuiltBottomSheetDialog bottomSheetDialog = new NewBuiltBottomSheetDialog(MainActivity.this,displayHeight);                bottomSheetDialog.setOnCustomButtonClickListener(new NewBuiltBottomSheetDialog.OnCustomButtonClickListener() {                    @Override                    public void onAddNoteButtonClick() {                        //打开新建笔记界面                        Toast.makeText(MainActivity.this,"新建笔记",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddFileButtonClick() {                        //打开新建文件界面                        Toast.makeText(MainActivity.this,"新建文件",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddPhotoButtonClick() {                        //打开新建图片界面                        Toast.makeText(MainActivity.this,"新建图片",Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onAddVideoButtonClick() {                        //打开新建视频界面                        Toast.makeText(MainActivity.this,"新建视频",Toast.LENGTH_SHORT).show();                    }                });                bottomSheetDialog.show();            }        });    }}

混淆配置

参考资料

项目demo下载地址

你可能感兴趣的文章
lnmp源码安装
查看>>
数据库事务基础知识
查看>>
javascript面向对象与原型
查看>>
SubVersion与MyEclipse整合
查看>>
ftp被动模式
查看>>
redis数据库安装配置
查看>>
英语学习网站
查看>>
C# 发送Http请求 - WebClient类
查看>>
Nagios监控平台搭建
查看>>
在F5上发布FTP应用
查看>>
在Exchange Server 2010中管理POP3和IMAP4协议访问
查看>>
Android网络开发框架Retrofit
查看>>
ocp-051-8
查看>>
Linux下安装telnet-server服务
查看>>
安装Exchange 2010
查看>>
一次防CC***案例
查看>>
认识linux的/etc/fstab和/etc/mtab
查看>>
linux磁盘管理
查看>>
pb 循环遍历文件
查看>>
win7下设置计划任务
查看>>