├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── sollian
│ │ └── bottomsheetdialog
│ │ ├── MainActivity.java
│ │ ├── MyApplication.java
│ │ ├── fragment
│ │ ├── CommonFragment.java
│ │ └── PanelFragment.java
│ │ └── widget
│ │ └── ListenFocusEditText.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── fragment_common.xml
│ └── fragment_panel.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── sollian
│ │ └── library
│ │ ├── BaseBottomSheetDialogFragment.java
│ │ ├── KeyboardObserver.java
│ │ ├── OnKeyboardChangeListener.java
│ │ ├── PanelFrameLayout.java
│ │ ├── PanelInputDialogFragment.java
│ │ ├── PanelInputDialogFragment2.java
│ │ └── Util.java
│ └── res
│ ├── anim
│ ├── slide_down.xml
│ └── slide_up.xml
│ └── values
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 30
5 | defaultConfig {
6 | applicationId "com.sollian.bottomsheetdialog"
7 | minSdkVersion 14
8 | targetSdkVersion 30
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_7
21 | targetCompatibility JavaVersion.VERSION_1_7
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(include: ['*.jar'], dir: 'libs')
27 | implementation project(':library')
28 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
29 | implementation 'com.android.support:appcompat-v7:27.1.1'
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
102 | * ps:statusbar可同理实现
103 | */
104 | protected boolean needHideNavigationBar() {
105 | return false;
106 | }
107 |
108 | @Override
109 | public void onDestroyView() {
110 | super.onDestroyView();
111 | isShowing = false;
112 | }
113 |
114 | @Override
115 | public void show(FragmentManager manager, String tag) {
116 | if (isShowing) {
117 | return;
118 | }
119 | isShowing = true;
120 | if (TextUtils.isEmpty(tag)) {
121 | tag = getClass().getSimpleName();
122 | }
123 |
124 | Fragment fragment = manager.findFragmentByTag(tag);
125 | if (fragment == null) {
126 | try {
127 | super.show(manager, tag);
128 | } catch (Exception e) {
129 | FragmentTransaction ft = manager.beginTransaction();
130 | ft.add(this, tag);
131 | ft.commitAllowingStateLoss();
132 | }
133 | }
134 | }
135 |
136 | @Deprecated
137 | @Override
138 | public final int show(FragmentTransaction transaction, String tag) {
139 | throw new UnsupportedOperationException("not support");
140 | }
141 |
142 | @Override
143 | public void onDismiss(DialogInterface dialog) {
144 | super.onDismiss(dialog);
145 | isShowing = false;
146 | if (dismissListener != null) {
147 | dismissListener.onDismiss(dialog);
148 | }
149 | }
150 |
151 | @Override
152 | public void dismiss() {
153 | if (!isShowing) {
154 | return;
155 | }
156 |
157 | Dialog dialog = getDialog();
158 | if (dialog == null) {
159 | return;
160 | }
161 |
162 | Util.hideKeyboard(dialog.getCurrentFocus());
163 | isShowing = false;
164 |
165 | getDialog().dismiss();
166 | }
167 |
168 | @Override
169 | public void dismissAllowingStateLoss() {
170 | dismiss();
171 | }
172 |
173 | public boolean isShowing() {
174 | return isShowing;
175 | }
176 |
177 | public void setDismissListener(DialogInterface.OnDismissListener dismissListener) {
178 | this.dismissListener = dismissListener;
179 | }
180 |
181 | /**
182 | * 解决按返回键不能展示退出动画的问题
183 | */
184 | private class MyDialog extends Dialog {
185 |
186 | MyDialog(@NonNull Context context, int themeResId) {
187 | super(context, themeResId);
188 | }
189 |
190 | @Override
191 | public void show() {
192 | if (needHideNavigationBar()) {
193 | //为了防止在Activity隐藏了NavigationBar的情况下,
194 | // 弹出DialogFragment时会短暂性的显示一下NavigationBar
195 | Window window = getWindow();
196 | window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
197 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
198 | super.show();
199 | Util.hideNavigationBar(window);
200 | window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
201 | } else {
202 | super.show();
203 | }
204 | }
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/KeyboardObserver.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.graphics.Rect;
6 | import android.os.Build;
7 | import android.view.View;
8 | import android.view.ViewTreeObserver;
9 |
10 | /**
11 | * @author sollian on 2018/3/6.
12 | */
13 | class KeyboardObserver implements ViewTreeObserver.OnGlobalLayoutListener {
14 | /**
15 | * 增加一个高度门限,低于此高度认为是系统的NavigationBar
16 | */
17 | private static final int THRESHOLD = Util.dp2px(100);
18 |
19 | private static final int SCREEN_HEIGHT = Util.getScreenHeight();
20 |
21 | private static final int MIN_PANEL_HEIGHT = Util.dp2px(220);
22 | private static final int MAX_PANEL_HEIGHT = Util.dp2px(380);
23 | private static final int DEFAULT_PANEL_HEIGHT = Util.dp2px(300);
24 |
25 | private static final String PREF_NAME = "keyboardPref";
26 | private static final String KEY_PENEL_HEIGHT = "keyPanelHeight";
27 |
28 | private View vTarget;
29 |
30 | private int minBottom;
31 | private int maxBottom;
32 |
33 | private boolean isKeyboardShowing;
34 | private int keyboardHeight;
35 | private int panelHeight = DEFAULT_PANEL_HEIGHT;
36 |
37 | private OnKeyboardChangeListener listener;
38 |
39 | private SharedPreferences sp;
40 |
41 | void setTarget(View v, OnKeyboardChangeListener listener) {
42 | if (v == null) {
43 | if (vTarget != null) {
44 | vTarget.getViewTreeObserver().removeGlobalOnLayoutListener(this);
45 | }
46 | this.listener = null;
47 | sp = null;
48 | return;
49 | }
50 | sp = v.getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
51 |
52 | vTarget = v;
53 | this.listener = listener;
54 |
55 | vTarget.getViewTreeObserver().addOnGlobalLayoutListener(this);
56 | }
57 |
58 | @Override
59 | public void onGlobalLayout() {
60 | int bottom = getBottomOnScreen(vTarget);
61 |
62 | boolean isShowing;
63 | if (bottom < SCREEN_HEIGHT - THRESHOLD) {
64 | isShowing = true;
65 | minBottom = bottom;
66 | } else {
67 | isShowing = false;
68 | maxBottom = bottom;
69 | }
70 |
71 | if (minBottom > 0 && maxBottom > 0) {
72 | keyboardHeight = maxBottom - minBottom;
73 | }
74 |
75 | if (isShowing) {
76 | int pHeight = getPanelHeight();
77 | if (pHeight != panelHeight) {
78 | panelHeight = pHeight;
79 | sp.edit().putInt(KEY_PENEL_HEIGHT, pHeight).apply();
80 | if (listener != null) {
81 | listener.onPanelHeightChange(pHeight);
82 | }
83 | }
84 | }
85 |
86 | if (isShowing != isKeyboardShowing) {
87 | isKeyboardShowing = isShowing;
88 | if (listener != null) {
89 | listener.onVisibilityChange(isShowing);
90 | }
91 | }
92 | }
93 |
94 | private static int getBottomOnScreen(View view) {
95 | int bottom;
96 | if (Build.VERSION.SDK_INT >= 16 && view.getFitsSystemWindows()) {
97 | Rect out = new Rect();
98 | view.getWindowVisibleDisplayFrame(out);
99 | bottom = out.bottom;
100 | } else {
101 | int h = view.getHeight();
102 | int[] loc = new int[2];
103 | view.getLocationOnScreen(loc);
104 | bottom = loc[1] + h;
105 | }
106 | return bottom;
107 | }
108 |
109 | private int getPanelHeight() {
110 | if (keyboardHeight < MIN_PANEL_HEIGHT) {
111 | return MIN_PANEL_HEIGHT;
112 | } else if (keyboardHeight > MAX_PANEL_HEIGHT) {
113 | return MAX_PANEL_HEIGHT;
114 | } else {
115 | return keyboardHeight;
116 | }
117 | }
118 |
119 | int getDefaultPanelHeight() {
120 | return sp.getInt(KEY_PENEL_HEIGHT, DEFAULT_PANEL_HEIGHT);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/OnKeyboardChangeListener.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | /**
4 | * @author sollian on 2018/3/6.
5 | */
6 | interface OnKeyboardChangeListener {
7 | void onVisibilityChange(boolean isShowing);
8 |
9 | void onPanelHeightChange(int newHeight);
10 | }
11 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/PanelFrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.FrameLayout;
8 |
9 | /**
10 | * 面板的容器
11 | *
12 | * @author sollian on 2018/3/2.
13 | */
14 | public class PanelFrameLayout extends FrameLayout {
15 |
16 | private boolean isShowing;
17 | private int panelHeight;
18 |
19 | public PanelFrameLayout(Context context) {
20 | super(context);
21 | }
22 |
23 | public PanelFrameLayout(Context context, AttributeSet attrs) {
24 | super(context, attrs);
25 | }
26 |
27 | public PanelFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
28 | super(context, attrs, defStyleAttr);
29 | }
30 |
31 | @Override
32 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
33 | if (isShowing) {
34 | super.onMeasure(widthMeasureSpec,
35 | MeasureSpec.makeMeasureSpec(panelHeight, MeasureSpec.EXACTLY));
36 | } else {
37 | setMeasuredDimension(getWidth(), 0);
38 | }
39 |
40 | }
41 |
42 | public void setPanelHeight(int panelHeight) {
43 | this.panelHeight = panelHeight;
44 | }
45 |
46 | public void setShowing(boolean showing) {
47 | isShowing = showing;
48 | }
49 |
50 | /**
51 | * 该方法添加View,preventRequestLayout==true时不会触发requestLayout调用
52 | */
53 | @Override
54 | public boolean addViewInLayout(View child,
55 | int index,
56 | ViewGroup.LayoutParams params,
57 | boolean preventRequestLayout) {
58 | return super.addViewInLayout(child, index, params, preventRequestLayout);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/PanelInputDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | import android.os.Bundle;
4 | import android.view.Gravity;
5 | import android.view.View;
6 | import android.view.Window;
7 | import android.view.WindowManager;
8 | import android.widget.EditText;
9 |
10 | /**
11 | * 适配性高,但ui交互欠友好
12 | *
13 | * @author sollian on 2018/3/6.
14 | */
15 |
16 | public class PanelInputDialogFragment extends BaseBottomSheetDialogFragment {
17 |
18 | /**
19 | * 非法状态
20 | */
21 | protected static final int STATE_INVALID = -1;
22 | /**
23 | * panel和软键盘都隐藏
24 | */
25 | protected static final int STATE_DEFAULT = 0;
26 | protected static final int STATE_KEYBOARD = 1;
27 | protected static final int STATE_PANEL = 2;
28 |
29 | private int state;
30 |
31 | private KeyboardObserver keyboardObserver;
32 |
33 | private View vRoot;
34 | private PanelFrameLayout vPanel;
35 | private EditText vEdit;
36 |
37 | @Override
38 | public void onActivityCreated(Bundle savedInstanceState) {
39 | super.onActivityCreated(savedInstanceState);
40 | Window window = getDialog().getWindow();
41 | if (window != null) {
42 | // Util.setStatusBarTransparent(window);
43 | // vRoot.setFitsSystemWindows(true);
44 |
45 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
46 | | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
47 |
48 | window.setGravity(Gravity.TOP);
49 | window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
50 | }
51 | }
52 |
53 | protected void init(View root, PanelFrameLayout panel, EditText editText) {
54 | vRoot = root;
55 | vPanel = panel;
56 | vEdit = editText;
57 |
58 | state = STATE_DEFAULT;
59 |
60 | View.OnClickListener clickListener = new MyOnClickListener();
61 | vRoot.setOnClickListener(clickListener);
62 | vEdit.setOnClickListener(clickListener);
63 |
64 | keyboardObserver = new KeyboardObserver();
65 | keyboardObserver.setTarget(vRoot, new OnKeyboardChangeListener() {
66 | @Override
67 | public void onVisibilityChange(boolean isShowing) {
68 | if (isShowing) {
69 | changeState(STATE_KEYBOARD);
70 | } else {
71 | switch (state) {
72 | case STATE_KEYBOARD:
73 | changeState(STATE_DEFAULT);
74 | break;
75 | default:
76 | break;
77 | }
78 | }
79 | }
80 |
81 | @Override
82 | public void onPanelHeightChange(int newHeight) {
83 | vPanel.setPanelHeight(newHeight);
84 | }
85 | });
86 |
87 | vPanel.setPanelHeight(keyboardObserver.getDefaultPanelHeight());
88 | }
89 |
90 | protected int getState() {
91 | return state;
92 | }
93 |
94 | protected void changeState(int newState) {
95 | int oldState = state;
96 | state = newState;
97 | beforeStateChange(oldState, newState);
98 |
99 | if (oldState != newState) {
100 | performChangeState(oldState, newState);
101 | }
102 | }
103 |
104 | private void performChangeState(int oldState, int newState) {
105 | switch (newState) {
106 | case STATE_PANEL:
107 | vPanel.setShowing(true);
108 | if (oldState == STATE_DEFAULT) {
109 | vPanel.requestLayout();
110 | } else {
111 | Util.hideKeyboard(vEdit);
112 | }
113 | break;
114 | case STATE_DEFAULT:
115 | vPanel.setShowing(false);
116 | Util.hideKeyboard(vEdit);
117 | break;
118 | case STATE_KEYBOARD:
119 | vPanel.setShowing(false);
120 | Util.showKeyboard(vEdit);
121 | break;
122 | default:
123 | break;
124 | }
125 | }
126 |
127 | protected void beforeStateChange(int oldState, int newState) {
128 | }
129 |
130 | @Override
131 | public void onDestroy() {
132 | super.onDestroy();
133 | if (keyboardObserver != null) {
134 | keyboardObserver.setTarget(null, null);
135 | }
136 | }
137 |
138 | private class MyOnClickListener implements View.OnClickListener {
139 |
140 | @Override
141 | public void onClick(View v) {
142 | if (v == vRoot) {
143 | dismiss();
144 | } else if (v == vEdit) {
145 | changeState(STATE_KEYBOARD);
146 | }
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/PanelInputDialogFragment2.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | import android.os.Bundle;
4 | import android.view.Gravity;
5 | import android.view.View;
6 | import android.view.Window;
7 | import android.view.WindowManager;
8 | import android.widget.EditText;
9 |
10 | /**
11 | * ui交互更加友好,但适配性可能不高
12 | *
13 | * @author sollian on 2018/3/6.
14 | */
15 | @Deprecated
16 | public class PanelInputDialogFragment2 extends BaseBottomSheetDialogFragment {
17 | protected static final int STATE_DEFAULT = 0;
18 | protected static final int STATE_KEYBOARD = 1;
19 | protected static final int STATE_EMOJI = 2;
20 |
21 | private int state;
22 |
23 | private KeyboardObserver keyboardObserver;
24 |
25 | private View vRoot;
26 | private PanelFrameLayout vPanel;
27 | private EditText vEdit;
28 |
29 | @Override
30 | public void onActivityCreated(Bundle savedInstanceState) {
31 | super.onActivityCreated(savedInstanceState);
32 | Window window = getDialog().getWindow();
33 | if (window != null) {
34 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
35 | | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
36 | }
37 | }
38 |
39 | protected void init(View root, PanelFrameLayout panel, EditText editText) {
40 | vRoot = root;
41 | vPanel = panel;
42 | vEdit = editText;
43 |
44 | state = STATE_DEFAULT;
45 |
46 | vEdit.setOnClickListener(new View.OnClickListener() {
47 | @Override
48 | public void onClick(View v) {
49 | changeState(STATE_KEYBOARD);
50 | }
51 | });
52 |
53 | vEdit.setOnLongClickListener(new View.OnLongClickListener() {
54 | @Override
55 | public boolean onLongClick(View v) {
56 | changeState(STATE_KEYBOARD);
57 | return false;
58 | }
59 | });
60 |
61 | keyboardObserver = new KeyboardObserver();
62 | keyboardObserver.setTarget(vRoot, new OnKeyboardChangeListener() {
63 | @Override
64 | public void onVisibilityChange(boolean isShowing) {
65 | if (isShowing) {
66 | changeState(STATE_KEYBOARD);
67 | } else {
68 | switch (state) {
69 | case STATE_KEYBOARD:
70 | changeState(STATE_DEFAULT);
71 | break;
72 | default:
73 | break;
74 | }
75 | }
76 |
77 | Util.postDelayed2UI(new Runnable() {
78 | @Override
79 | public void run() {
80 | updateWindowOffset(0);
81 | }
82 | }, 0);
83 | }
84 |
85 | @Override
86 | public void onPanelHeightChange(int newHeight) {
87 | vPanel.setPanelHeight(newHeight);
88 | }
89 | });
90 |
91 | vPanel.setPanelHeight(keyboardObserver.getDefaultPanelHeight());
92 | }
93 |
94 | protected int getState() {
95 | return state;
96 | }
97 |
98 | protected void changeState(int state) {
99 | if (this.state == state) {
100 | return;
101 | }
102 | onStateChange(this.state, state);
103 | switch (state) {
104 | case STATE_EMOJI:
105 | vPanel.setShowing(true);
106 | if (this.state == STATE_KEYBOARD) {
107 | pinWindow();
108 | Util.hideKeyboard(vEdit);
109 | Util.postDelayed2UI(new Runnable() {
110 | @Override
111 | public void run() {
112 | vPanel.requestLayout();
113 | }
114 | }, 50);
115 | } else {
116 | vPanel.requestLayout();
117 | }
118 | break;
119 | case STATE_DEFAULT:
120 | vPanel.setShowing(false);
121 | Util.hideKeyboard(vEdit);
122 | break;
123 | case STATE_KEYBOARD:
124 | vPanel.setShowing(false);
125 | if (this.state == STATE_EMOJI) {
126 | pinWindow();
127 | Util.postDelayed2UI(new Runnable() {
128 | @Override
129 | public void run() {
130 | Util.showKeyboard(vEdit);
131 | }
132 | }, 0);
133 | } else {
134 | Util.showKeyboard(vEdit);
135 | }
136 | break;
137 | default:
138 | break;
139 | }
140 | this.state = state;
141 | }
142 |
143 | protected void onStateChange(int oldState, int newState) {
144 |
145 | }
146 |
147 | private void pinWindow() {
148 | int[] loc = new int[2];
149 | vRoot.getLocationOnScreen(loc);
150 | updateWindowOffset(loc[1] - Util.getStatusBarHeight());
151 | }
152 |
153 | private void updateWindowOffset(int y) {
154 | Window window = getDialog().getWindow();
155 | if (window == null) {
156 | return;
157 | }
158 | WindowManager.LayoutParams attrs = window.getAttributes();
159 | if (attrs == null) {
160 | return;
161 | }
162 | attrs.gravity = y == 0 ? Gravity.BOTTOM : Gravity.TOP;
163 | attrs.y = y;
164 | window.setAttributes(attrs);
165 | }
166 |
167 | @Override
168 | public void onDestroyView() {
169 | super.onDestroyView();
170 | keyboardObserver.setTarget(null, null);
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/library/src/main/java/com/sollian/library/Util.java:
--------------------------------------------------------------------------------
1 | package com.sollian.library;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.graphics.Color;
6 | import android.os.Build;
7 | import android.os.Handler;
8 | import android.os.Looper;
9 | import android.support.annotation.NonNull;
10 | import android.support.v4.app.FragmentActivity;
11 | import android.util.DisplayMetrics;
12 | import android.util.TypedValue;
13 | import android.view.View;
14 | import android.view.Window;
15 | import android.view.WindowManager;
16 | import android.view.inputmethod.InputMethodManager;
17 | import java.lang.reflect.Field;
18 |
19 | /**
20 | * @author sollian on 2018/3/20.
21 | */
22 |
23 | public class Util {
24 |
25 | private static Application context;
26 |
27 | private static final DisplayMetrics sDisplayMetrics = new DisplayMetrics();
28 | private static final Handler handler = new Handler(Looper.getMainLooper());
29 | private static int sStatusBarHeight = -1;
30 |
31 | public static void init(Application context) {
32 | Util.context = context;
33 | ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
34 | .getDefaultDisplay().getMetrics(sDisplayMetrics);
35 | }
36 |
37 | public static void showKeyboard(View vFocus) {
38 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
39 | if (imm != null
40 | // && !imm.isActive()
41 | && vFocus != null) {
42 | imm.showSoftInput(vFocus, InputMethodManager.SHOW_IMPLICIT);
43 | }
44 | }
45 |
46 | public static void hideKeyboard(View vFocus) {
47 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
48 | if (imm != null
49 | && imm.isActive()
50 | && vFocus != null) {
51 | imm.hideSoftInputFromWindow(vFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
52 | }
53 | }
54 |
55 | public static int dp2px(float dpValue) {
56 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue,
57 | sDisplayMetrics);
58 | }
59 |
60 | public static int getScreenHeight() {
61 | return sDisplayMetrics.heightPixels;
62 | }
63 |
64 | public static void setStatusBarTransparent(Window window) {
65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
66 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
67 | window.getDecorView().setSystemUiVisibility(
68 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
69 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
70 | );
71 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
72 | window.setStatusBarColor(Color.TRANSPARENT);
73 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
74 | window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
75 | }
76 | }
77 |
78 | public static void postDelayed2UI(Runnable r, long delayMillis) {
79 | handler.postDelayed(r, delayMillis);
80 | }
81 |
82 | public static int getStatusBarHeight() {
83 | if (sStatusBarHeight == -1) {
84 | int sbar = 0;
85 | try {
86 | Class> c = Class.forName("com.android.internal.R$dimen");
87 | Object obj = c.newInstance();
88 | Field field = c.getField("status_bar_height");
89 | int x = Integer.parseInt(field.get(obj).toString());
90 | sbar = context.getResources().getDimensionPixelSize(x);
91 | } catch (Exception e1) {
92 | e1.printStackTrace();
93 | } finally {
94 | sStatusBarHeight = sbar;
95 | }
96 |
97 | try {
98 | //Use 25dp if no status bar height found
99 | if (sStatusBarHeight == 0) {
100 | DisplayMetrics metrics = context
101 | .getResources().getDisplayMetrics();
102 | sStatusBarHeight = (int) (25 * metrics.scaledDensity);
103 | }
104 | } catch (Exception ignored) {
105 | }
106 | }
107 |
108 | return sStatusBarHeight;
109 | }
110 |
111 | public static void hideNavigationBar(@NonNull Window window) {
112 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
113 | View decorView = window.getDecorView();
114 | int uiFlags = decorView.getSystemUiVisibility(); // hide status bar
115 | uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
116 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
117 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
118 | uiFlags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
119 | } else {
120 | uiFlags |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
121 | }
122 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
123 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
124 | }
125 | decorView.setSystemUiVisibility(uiFlags);
126 | }
127 | }
128 |
129 | public static int getScreenWidth(Context context) {
130 | return context.getResources().getDisplayMetrics().widthPixels;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/slide_down.xml:
--------------------------------------------------------------------------------
1 |
2 |