package net.coding.program.common.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import net.coding.program.R;
/**
* Created by Carlos2015 on 2015/8/19.
* 输入控件(common_enter_emoji)支持切换动画的父容器,必须保证它只有两个子控件,并且输入控件是第二个
*/
public class EnterLayoutAnimSupportContainer extends FrameLayout {
private String TAG = "EnterLayoutAnimSupportContainer";
private ViewGroup mContent;
private FrameLayout mEnter;
private boolean isFirstLayout = true;
private boolean isAdjustResize = true;
private int mEnterLayoutBottomMargin;
private int mContentHeight;
private int mEnterHeight;
private int lastEnterLayoutBottomMargin;
private LayoutParams lp_enter, lp_content;
private EditText comment;
private int minCommentHeight;
private int minEnterHeight;
private int minVoiceLayoutTop, minEmojikeyboardLayoutTop;
private int minEnterLayoutBottomMargin;
private ViewGroup voiceLayout, mInputBox;
private LayoutParams lp_voice, lp_emoji;
private OnEnterLayoutBottomMarginChanagedCallBack mOnEnterLayoutBottomMarginChanagedCallBack;
private Editable tempData;
private Handler mHandler;
private boolean isEnterHeightChanaged;
private int inputboxHeight;
private FrameLayout mPanelLayout;
/**
* mEnter关闭时的绝对y坐标
*/
public int closeY;
/**
* mEnter打开时的绝对y坐标
*/
public int openY;
/**
* mEnter关闭且输入法弹出将mEnter顶上去时的绝对y坐标
*/
public int softkeyboardOpenY;
public int orignalHeight;
private int mY;
public EnterLayoutAnimSupportContainer(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.EnterLayoutAnimSupportContainer);
isAdjustResize = a.getBoolean(R.styleable.EnterLayoutAnimSupportContainer_isAdjustResize, false);
a.recycle();
}
public void setEnterLayoutBottomMargin(int mEnterLayoutBottomMargin) {
this.mEnterLayoutBottomMargin = mEnterLayoutBottomMargin;
isEnterHeightChanaged = false;
requestLayout();
}
private int mOldHeight = -1;
private SoftKeyBordState mSoftKeyBordState = SoftKeyBordState.Hide;
public SoftKeyBordState getSoftKeyBordState() {
return mSoftKeyBordState;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 由当前布局被键盘挤压,获知,由于键盘的活动,导致布局将要发生变化。
do {
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int height = MeasureSpec.getSize(heightMeasureSpec);
Log.d(TAG, "onMeasure, width: " + width + " height: " + height);
if (height < 0) {
break;
}
if (mOldHeight < 0) {
mOldHeight = height;
break;
}
final int offset = mOldHeight - height;
mOldHeight = height;
if (offset == 0) {
Log.d(TAG, "" + offset + " == 0 break;");
mSoftKeyBordState = SoftKeyBordState.Hide;
break;
}
if (mEnter != null && mPanelLayout == null) {
mPanelLayout = (FrameLayout) mEnter.getChildAt(1);
}
if (mPanelLayout == null) {
Log.d(TAG, "bottom == null break;");
break;
}
// 检测到真正的 由于键盘收起触发了本次的布局变化
if (offset > 0) {
//键盘弹起 (offset > 0,高度变小)
mSoftKeyBordState = SoftKeyBordState.Opening;
mEnterLayoutBottomMargin = minEnterLayoutBottomMargin;
mPanelLayout.setVisibility(View.GONE);
} else {
mSoftKeyBordState = SoftKeyBordState.Closing;
//键盘收回 (offset < 0,高度变大)
if (!isCloseInputMethodBySelf) {
isCloseInputMethodBySelf = true;
mPanelLayout.setVisibility(View.VISIBLE);
mEnterLayoutBottomMargin = 0;
} else {
mPanelLayout.setVisibility(View.GONE);
mEnterLayoutBottomMargin = minEnterLayoutBottomMargin;
}
}
} while (false);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public enum SoftKeyBordState {
Opening, Closing, Hide
}
private boolean isCloseInputMethodBySelf = true;
public void setCloseInputMethodBySelf(boolean closeBySelf) {
isCloseInputMethodBySelf = closeBySelf;
}
public boolean isPanelLauoutOpen() {
return mEnterLayoutBottomMargin == 0;
}
/**
* 判断输入法弹出时会不会拉伸布局
*
* @return
*/
public boolean isAdjustResize() {
return isAdjustResize;
}
public void setOnEnterLayoutBottomMarginChanagedCallBack(OnEnterLayoutBottomMarginChanagedCallBack callBack) {
this.mOnEnterLayoutBottomMarginChanagedCallBack = callBack;
}
public FrameLayout getPanelLayout() {
return mPanelLayout;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if (1 == 1) {
super.onLayout(changed, left, top, right, bottom);
return;
}
if (isFirstLayout && getVisibility() != View.GONE) {
mContent = (ViewGroup) getChildAt(0);
lp_content = (LayoutParams) mContent.getLayoutParams();
mEnter = (FrameLayout) getChildAt(1);
mPanelLayout = (FrameLayout) mEnter.getChildAt(1);
lp_enter = (LayoutParams) mEnter.getLayoutParams();
mEnterLayoutBottomMargin = lp_enter.bottomMargin;
minEnterLayoutBottomMargin = mEnterLayoutBottomMargin;
lp_enter.gravity = Gravity.BOTTOM | Gravity.LEFT;
comment = (EditText) mEnter.findViewById(R.id.comment);
mInputBox = (ViewGroup) mEnter.findViewById(R.id.mInputBox);
voiceLayout = (ViewGroup) mEnter.findViewById(R.id.voiceLayout);
lp_voice = (LayoutParams) voiceLayout.getLayoutParams();
lp_emoji = (LayoutParams) mEnter.findViewById(R.id.emojiKeyboardLayout).getLayoutParams();
isFirstLayout = false;
orignalHeight = bottom - top;
inputboxHeight = mInputBox.getMeasuredHeight();
int[] location = new int[2];
getLocationInWindow(location);
mY = location[1];
lastEnterLayoutBottomMargin = mEnterLayoutBottomMargin;
if (isAdjustResize) {
lp_content.height = -1;
}
//当输入框中文本内容大于1行时,此时获取不到输入框的最小高度,因此将文本保存起来,清空输入框,通过
//第一个延迟消息得到单行输入框的高度(最小高度),第二个延迟消息将暂时保存的文本放入输入框,此时整个输入控件的
//显示就会正常
if (isAdjustResize && mEnter.getVisibility() != View.GONE && comment.getLineCount() > 1) {
tempData = comment.getText();
comment.setText("");
final int status = mEnter.getVisibility();
mEnter.setVisibility(View.GONE);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
if (comment.getLineCount() <= 1) {
if (!TextUtils.isEmpty(comment.getText())) {
tempData = comment.getText();
}
mEnter.setVisibility(status);
mHandler.sendEmptyMessageDelayed(2, 100);
} else {
tempData = comment.getText();
comment.setText("");
mEnter.setVisibility(View.GONE);
mHandler.sendEmptyMessageDelayed(1, 100);
}
break;
case 2:
comment.setText(tempData);
tempData = null;
mHandler = null;
break;
}
}
};
mHandler.sendEmptyMessageDelayed(1, 200);
} else {
if (mEnter.getVisibility() != View.GONE) {
//comment最小高度,当行数发生变化时,它的高度会随之改变
minEnterHeight = mEnter.getMeasuredHeight();
minCommentHeight = comment.getMeasuredHeight();
minVoiceLayoutTop = lp_voice.topMargin;
minEmojikeyboardLayoutTop = lp_emoji.topMargin;
}
}
}
if (minEnterHeight == 0 && mEnter.getVisibility() != View.GONE) {
//comment最小高度,当行数发生变化时,它的高度会随之改变
minEnterHeight = mEnter.getMeasuredHeight();
minCommentHeight = comment.getMeasuredHeight();
minVoiceLayoutTop = lp_voice.topMargin;
minEmojikeyboardLayoutTop = lp_emoji.topMargin;
inputboxHeight = mInputBox.getMeasuredHeight();
}
if (!isEnterHeightChanaged) {
if (mEnter.getVisibility() != View.GONE) {
int commentHeight = comment.getMeasuredHeight();
int dH = commentHeight - minCommentHeight;
mEnterHeight = minEnterHeight + dH;
if (dH > 0) {
lp_enter.height = mEnterHeight;
lp_voice.topMargin = minVoiceLayoutTop + dH;
lp_emoji.topMargin = minEmojikeyboardLayoutTop + dH;
} else {
lp_voice.topMargin = minVoiceLayoutTop;
lp_emoji.topMargin = minEmojikeyboardLayoutTop;
}
closeY = mY + orignalHeight - (mEnterHeight + mEnterLayoutBottomMargin);
openY = closeY + mEnterLayoutBottomMargin;
}
int content_bottom = bottom - top - (mEnterHeight + mEnterLayoutBottomMargin);
int cL = 0, cR = 0, cT = 0, cB = 0;
int eL = 0, eR = 0, eT = 0, eB = 0;
if (isAdjustResize) {
// lp_enter.bottomMargin = mEnterLayoutBottomMargin;
//加上这一句防止mContent的高度有时显示不正确
if (lp_content.height == -1) {
lp_content.height = content_bottom - getPaddingTop() - lp_content.topMargin;
}
cL = getPaddingLeft() + lp_content.leftMargin;
cT = getPaddingTop() + lp_content.topMargin;
cR = cL + mContent.getMeasuredWidth();
cB = content_bottom;
eL = lp_enter.leftMargin + getPaddingLeft();
eT = content_bottom;
eR = eL + mEnter.getMeasuredWidth();
eB = mEnterHeight + content_bottom;
} else {
cL = getPaddingLeft() + lp_content.leftMargin;
cT = getPaddingTop() + lp_content.topMargin;
cR = cL + mContent.getMeasuredWidth();
cB = cT + mContent.getMeasuredHeight();
eL = lp_enter.leftMargin + getPaddingLeft();
eT = content_bottom;
eR = eL + mEnter.getMeasuredWidth();
eB = mEnterHeight + content_bottom;
}
mContent.layout(cL, cT, cR, cB);
mEnter.layout(eL, eT, eR, eB);
lp_enter.bottomMargin = mEnterLayoutBottomMargin;
if (mOnEnterLayoutBottomMarginChanagedCallBack != null) {
mOnEnterLayoutBottomMarginChanagedCallBack.onChanage(mEnterLayoutBottomMargin, lastEnterLayoutBottomMargin);
}
lastEnterLayoutBottomMargin = mEnterLayoutBottomMargin;
} else {
super.onLayout(changed, left, top, right, bottom);
}
}
public interface OnEnterLayoutBottomMarginChanagedCallBack {
void onChanage(int lastBottomMargin, int newBottomMargin);
}
}