Demand analysis:
When we click on the input box, it will bring up the input method soft keyboard. If we do not do anything, the PopupWindow comment window may be crowded to the top of the screen. Even worse, we can’t see our input box, and we can’t even see what we type, which will make the user experience very bad! Let’s take a look at our renderings below:
1. As can be seen from the above figure, the input method pops up and hides. For our comment window, the height is always the same, which can bring users a better experience!
2. By default, we set the PopupWindow popup height to 80% of the screen, but you can set other proportions in your code.
First, we rewrote the RelativeLayout root layout to listen for input method state
KeyboardLayout.java
package com.t20.commentdemo.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.RelativeLayout;
RelativeLayout with keyboard listener
public class KeyboardLayout extends RelativeLayout {
private KeyboardLayoutListener mListener;
private boolean mIsKeyboardActive = false; // Whether the input method is active
private int mKeyboardHeight = 0; // Input method height
private Context mContext;
public KeyboardLayout(Context context) {
this(context, null.0);
}
public KeyboardLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
// Listen for layout changes
getViewTreeObserver().addOnGlobalLayoutListener(
new KeyboardOnGlobalChangeListener());
}
private class KeyboardOnGlobalChangeListener implements
OnGlobalLayoutListener {
int mScreenHeight = 0;
private int getScreenHeight(a) {
if (mScreenHeight > 0) {
return mScreenHeight;
}
mScreenHeight = ((Activity) mContext).getWindowManager()
.getDefaultDisplay().getHeight();
return mScreenHeight;
}
@Override
// Called when the global layout in the view tree changes or the visual state of a view in the view tree changes
public void onGlobalLayout(a) {
Rect rect = new Rect();
// Get the display range of the current page window
((Activity) getContext()).getWindow().getDecorView()
.getWindowVisibleDisplayFrame(rect);
int screenHeight = getScreenHeight();
int keyboardHeight = screenHeight - rect.bottom; // Input method height
boolean isActive = false;
if (Math.abs(keyboardHeight) > screenHeight / 5) {
isActive = true; // Over 1/5 of the screen indicates that the input method is popped up
mKeyboardHeight = keyboardHeight;
}
mIsKeyboardActive = isActive;
if(mListener ! =null) { mListener.onKeyboardStateChanged(isActive, keyboardHeight); }}}public void setKeyboardListener(KeyboardLayoutListener listener) {
mListener = listener;
}
public KeyboardLayoutListener getKeyboardListener(a) {
return mListener;
}
public boolean isKeyboardActive(a) {
return mIsKeyboardActive;
}
/** * Get the input method height **@return* /
public int getKeyboardHeight(a) {
return mKeyboardHeight;
}
public interface KeyboardLayoutListener {
/ * * *@paramIsActive * indicates whether the input method isActive@paramKeyboardHeight * Input panel height */
void onKeyboardStateChanged(boolean isActive, int keyboardHeight); }}Copy the code
Second, we have a custom PopupWindow that we can reference directly to other projects later
CommentPopupWindow.java
package com.t20.commentdemo.view;
import com.t20.commentdemo.R;
import com.t20.commentdemo.view.KeyboardLayout.KeyboardLayoutListener;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class CommentPopupWindow extends PopupWindow {
private Context mContext;
private OnClickListener mOnClickListener;
private OnFocusChangeListener mOnFocusChangeListener;
private View mPopupWindowView;
// popupWindow layout
private RelativeLayout mPopupWindowViewLayout;
// The entire screen width
private int mScreenWidth;
// The height of the entire screen
private int mScreenHeight;
// popupWindow specifies the height of the layout as a percentage of the screen
private final double mPopupWindowHeightForScreenPercent = 0.8;
private LinearLayout mCommentPopupWindowHead;
private LinearLayout mCommentPopupWindowFoot;
// Total number of comments
private TextView mTextViewCommentCount;
// Close the window
private TextView mTextViewClose;
// List view of comments
private ListView mListViewComments;
// Enter the comment content
private EditText mEditTextInput;
// Send button
private TextView mTextViewSend;
// Set the width and height of the control
private android.widget.LinearLayout.LayoutParams mLayoutParams;
public EditText getmEditTextInput(a) {
return mEditTextInput;
}
public void setmEditTextInput(EditText mEditTextInput) {
this.mEditTextInput = mEditTextInput;
}
public CommentPopupWindow(Context context, OnClickListener onClickListener, OnFocusChangeListener onFocusChangeListener) {
super(context);
mContext = context;
mOnClickListener = onClickListener;
mOnFocusChangeListener = onFocusChangeListener;
initDate();
initView();
setPopupWindowSize();
initEvent();
}
private void initDate(a) {
// Get the screen width and height.
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
}
private void initView(a) {
// Get the layout
mPopupWindowView = View.inflate(mContext, R.layout.comment_dialog, null);
// Get the control
mPopupWindowViewLayout = (RelativeLayout) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_layout);
mCommentPopupWindowHead = (LinearLayout) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_head);
mCommentPopupWindowFoot = (LinearLayout) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_foot);
mTextViewCommentCount = (TextView) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_tv_commentsCount);
mTextViewClose = (TextView) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_tv_close);
mListViewComments = (ListView) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_lv);
mEditTextInput = (EditText) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_et_input);
mTextViewSend = (TextView) mPopupWindowView.findViewById(R.id.commentPopupWindow_comment_tv_send);
mLayoutParams = (android.widget.LinearLayout.LayoutParams) mPopupWindowViewLayout.getLayoutParams();
}
private void setPopupWindowSize(a) {
// Add a margin to the ListView -- note the BUG: the maximum layout cannot be relative
mCommentPopupWindowHead.measure(0.0);
int headHeight = mCommentPopupWindowHead.getMeasuredHeight();// Get the head height
mCommentPopupWindowFoot.measure(0.0);
int footHeight = mCommentPopupWindowFoot.getMeasuredHeight();// Get the tail height
mListViewComments.setPadding(0, headHeight, 0, footHeight);
this.setContentView(mPopupWindowView);
// Click outside the window (click outside the area to close the window)
this.setOutsideTouchable(true);
// Form is clickable
this.setFocusable(true);
// Fix bugs in earlier versions of Android (clicking "Back" will also make them disappear, without affecting your background)
this.setBackgroundDrawable(new BitmapDrawable());
// Set the height of the content layout (as a percentage of the screen height)
mLayoutParams.height = (int) (mScreenHeight * mPopupWindowHeightForScreenPercent);
mPopupWindowViewLayout.setLayoutParams(mLayoutParams);
// Set the popupWindow width to be the same as the screen width
this.setWidth(mScreenWidth);
// Set the popupWindow height to the same as the content height
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
// Pop overlays the input method
this.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
// This sentence lets pop adapt to the input state
this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
private void initEvent(a) {
mTextViewClose.setOnClickListener(mOnClickListener);
mEditTextInput.setOnFocusChangeListener(mOnFocusChangeListener);
mTextViewSend.setOnClickListener(mOnClickListener);
}
/** * Changes the height of the comment popupWindow layout * depending on whether the input keyboard pops up@param keyboardLayout
*/
public void setPopupWindowFroKeyboard(KeyboardLayout keyboardLayout ){
if(keyboardLayout ! =null) {
keyboardLayout.setKeyboardListener(new KeyboardLayoutListener() {
@Override
public void onKeyboardStateChanged(boolean isActive,int keyboardHeight) {
if (isActive) { // The input method is displayed
setpopupWindowHeight(keyboardHeight);
} else {// The input method is hidden
setpopupWindowHeight(0); }}}); }}// Set the height of the comment window
public void setpopupWindowHeight(int keyboardHeight) {
mLayoutParams.height = (int) (mScreenHeight * mPopupWindowHeightForScreenPercent)- keyboardHeight; mPopupWindowViewLayout.setLayoutParams(mLayoutParams); }}Copy the code
Three, we activity_main. XML layout, com.t20.com mentdemo. The KeyboardLayout is KeyboardLayout Java the full path
<com.t20.commentdemo.view.KeyboardLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/keyboardLayout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="# 000"
tools:context=".MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:onClick="openCommentWindow"
android:textColor="#fff"
android:text="Click to pop up the comment window" />
</com.t20.commentdemo.view.KeyboardLayout>
Copy the code
Finally, the popup call to the CommentPopupWindow in the activity mainActivity. Java
package com.t20.commentdemo;
import com.t20.commentdemo.view.CommentPopupWindow;
import com.t20.commentdemo.view.KeyboardLayout;
import android.os.Bundle;
import android.app.Activity;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
public class MainActivity extends Activity {
// Maximum KeyboardLayout(RelativeLayout rewrite)
private KeyboardLayout mKeyboardLayoutRoot;
/ / comment
private CommentPopupWindow mCommentPopupWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1, hide the title bar, set before loading the layout (compatible with Android2.3.3 version)
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hide the status bar
//getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
// Get the control
mKeyboardLayoutRoot=(KeyboardLayout) findViewById(R.id.keyboardLayout_root);
}
/** * Click the pop-up comment window event *@param view
*/
public void openCommentWindow(View view) {
// Define the popup window
mCommentPopupWindow=new CommentPopupWindow(MainActivity.this, onClickListener, onFocusChangeListener);
/ / display PopupWindow
mCommentPopupWindow.showAtLocation(mKeyboardLayoutRoot, Gravity.BOTTOM,0.0);
// Make the input box lose focus
mCommentPopupWindow.getmEditTextInput().clearFocus();
// Change the height of the comment popupWindow layout depending on whether the input keyboard pops up
mCommentPopupWindow.setPopupWindowFroKeyboard(mKeyboardLayoutRoot);
}
/** * listen for click events in comments */
private OnClickListener onClickListener=new OnClickListener() {
@Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch (view.getId()) {
// Close the button
case R.id.commentPopupWindow_comment_tv_close:
mCommentPopupWindow.dismiss();
break;
// Click to comment
case R.id.commentPopupWindow_comment_tv_send:
break; }}};/** * listen for focus change events in comments */
private OnFocusChangeListener onFocusChangeListener=new OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
// TODO Auto-generated method stub
switch (view.getId()) {
case R.id.commentPopupWindow_comment_et_input:
// Get the focus
if (hasFocus) {
// During focusing, determine whether the user is logged in. If not, the login interface can be redirected
}
break; }}}; }Copy the code