package net.coding.program.common.enter;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.skyfishjy.library.RippleBackground;
import net.coding.program.R;
import net.coding.program.common.Global;
import net.coding.program.common.MyImageGetter;
import net.coding.program.message.EmojiFragment;
/**
* Created by chaochen on 14-10-31.
* 输入框
*/
// // FIXME: delete this class
public class EnterEmojiLayout extends EnterLayout {
static String emojiIcons[][] = {{
"smiley",
"heart_eyes",
"pensive",
"flushed",
"grin",
"kissing_heart",
"wink",
"angry",
"disappointed",
"disappointed_relieved",
"sob",
"stuck_out_tongue_closed_eyes",
"rage",
"persevere",
"unamused",
"smile",
"mask",
"kissing_face",
"sweat",
"joy",
"ic_keyboard_delete"
}, {
"blush",
"cry",
"stuck_out_tongue_winking_eye",
"fearful",
"cold_sweat",
"dizzy_face",
"smirk",
"scream",
"sleepy",
"confounded",
"relieved",
"smiling_imp",
"ghost",
"santa",
"dog",
"pig",
"cat",
"a00001",
"a00002",
"facepunch",
"ic_keyboard_delete"
}, {
"fist",
"v",
"muscle",
"clap",
"point_left",
"point_up_2",
"point_right",
"point_down",
"ok_hand",
"heart",
"broken_heart",
"sunny",
"moon",
"star2",
"zap",
"cloud",
"lips",
"rose",
"coffee",
"birthday",
"ic_keyboard_delete"
}, {
"clock10",
"beer",
"mag",
"iphone",
"house",
"car",
"gift",
"soccer",
"bomb",
"gem",
"alien",
"my100",
"money_with_wings",
"video_game",
"hankey",
"sos",
"zzz",
"microphone",
"umbrella",
"book",
"ic_keyboard_delete"}
};
static String monkeyIcons[][] = new String[][]{{
"coding_emoji_01",
"coding_emoji_02",
"coding_emoji_03",
"coding_emoji_04",
"coding_emoji_05",
"coding_emoji_06",
"coding_emoji_07",
"coding_emoji_08"
}, {
"coding_emoji_09",
"coding_emoji_10",
"coding_emoji_11",
"coding_emoji_12",
"coding_emoji_13",
"coding_emoji_14",
"coding_emoji_15",
"coding_emoji_16"
}, {
"coding_emoji_17",
"coding_emoji_18",
"coding_emoji_19",
"coding_emoji_20",
"coding_emoji_21",
"coding_emoji_22",
"coding_emoji_23",
"coding_emoji_24"
}, {
"coding_emoji_25",
"coding_emoji_26",
"coding_emoji_27",
"coding_emoji_28",
"coding_emoji_29",
"coding_emoji_30",
"coding_emoji_31",
"coding_emoji_32",
}, {
"coding_emoji_33",
"coding_emoji_34",
"coding_emoji_35",
"coding_emoji_36",
"coding_emoji_38",
"coding_emoji_39",
"coding_emoji_40",
"coding_emoji_41",
}, {
"coding_emoji_42",
"coding_emoji_43",
}};
static String zhongqiuIcons[][] = new String[][]{{
"festival_emoji_01",
"festival_emoji_02",
"festival_emoji_03",
"festival_emoji_04",
"festival_emoji_05",
"festival_emoji_06",
"festival_emoji_07",
"festival_emoji_08"
}};
protected final View rootView;
protected int rootViewHigh = 0;
protected ViewGroup mInputBox;//文本输入框所在的布局容器
protected RippleBackground voiceLayout;
protected InputType mInputType;
protected boolean isSoftKeyBoard = false;
PageChangeListener pageChange = new PageChangeListener();
private CheckBox checkBoxEmoji;
private View emojiKeyboardLayout;
private LinearLayout emojiKeyboardIndicator;
private EmojiPagerAdapter mEmojiPagerAdapter;
private MonkeyPagerAdapter mMonkeyPagerAdapter;
private ZhongqiuPagerAdapter mZhongqiuPagerAdapter;
private View selectEmoji;
private View selectMonkey;
private View selectZhongqiu;
private MyImageGetter myImageGetter;
private Activity mActivity;
private boolean firstLayout = true;
private int contentViewHeight;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowLp;
private ImageView mWindowView;
private int statusBarHeight;
private FrameLayout mPanelLayout;
private View.OnClickListener checkBoxEmojiOnClicked = new View.OnClickListener() {
@Override
public void onClick(View v) {
content.requestFocus();
if (checkBoxEmoji.isChecked()) {
rootViewHigh = rootView.getHeight();
final int bottomHigh = Global.dpToPx(100); // 底部虚拟按键高度,nexus5是73dp,以防万一,所以设大一点
int rootParentHigh = rootView.getRootView().getHeight();
//rootParentHigh - rootViewHigh > bottomHigh
if (isSoftKeyBoard) {
// 说明键盘已经弹出来了,等键盘消失后再设置 emoji keyboard 可见
if (commonEnterRoot != null) {
toggleInputTypeWithCloseSoftkeyboard(InputType.Emoji);
} else {
//兼容没有使用common_enter_emoji的输入控件
Global.popSoftkeyboard(mActivity, content, false);
mInputType = InputType.Emoji;
}
// 魅族手机的 rootView 无论输入法是否弹出高度都是不变的,只好搞个延时做这个事
rootView.postDelayed(new Runnable() {
@Override
public void run() {
rootView.setLayoutParams(rootView.getLayoutParams());
}
}, 50);
} else {
if (commonEnterRoot != null) {
toggleNoTextInput(InputType.Emoji);
} else {
//兼容没有使用common_enter_emoji的输入控件
emojiKeyboardLayout.setVisibility(View.VISIBLE);
}
rootViewHigh = 0;
}
} else {
if (commonEnterRoot != null) {
toggleSoftkeyboardWithCloseNoTextInput(InputType.Emoji);
} else {
//兼容没有使用common_enter_emoji的输入控件
Global.popSoftkeyboard(mActivity, content, true);
emojiKeyboardLayout.setVisibility(View.GONE);
}
}
}
};
public EnterEmojiLayout(final FragmentActivity activity, View.OnClickListener sendTextOnClick, Type type, EmojiType emojiType) {
super(activity, sendTextOnClick, type);
mActivity = activity;
myImageGetter = new MyImageGetter(activity);
mWindowManager = (WindowManager) mActivity.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
voiceLayout = (RippleBackground) activity.findViewById(R.id.voiceLayout);
mInputBox = (ViewGroup) activity.findViewById(R.id.mInputBox);
checkBoxEmoji = (CheckBox) activity.findViewById(R.id.popEmoji);
checkBoxEmoji.setOnClickListener(checkBoxEmojiOnClicked);
mPanelLayout = (FrameLayout) activity.findViewById(R.id.mPanelLayout);
rootView = mActivity.findViewById(android.R.id.content);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (firstLayout) {
firstLayout = false;
contentViewHeight = getContentViewHeight(activity);
}
if (mEnterLayoutAnimSupportContainer != null && mEnterLayoutAnimSupportContainer.softkeyboardOpenY == 0) {
//获取输入法软键盘的高度
int softkeyboardHeight = contentViewHeight - getContentViewHeight(activity);
if (softkeyboardHeight > contentViewHeight / 4) {
//为什么要再减去状态栏的高度才得到正确的mInputBox在软键盘弹出后的绝对y坐标???
mEnterLayoutAnimSupportContainer.softkeyboardOpenY = mEnterLayoutAnimSupportContainer.closeY - softkeyboardHeight - statusBarHeight;
Log.w("softkeyboardHeight", softkeyboardHeight + "");
}
}
int h = getContentViewHeight(activity);
if (contentViewHeight == h) {
// dropTempWindow();
isSoftKeyBoard = false;
// updateEnterLayoutBottom(0);
//Log.w("Test", "输入法已经隐藏");
} else if (contentViewHeight > h) {
isSoftKeyBoard = true;
}
if (rootViewHigh == 0) {
return;
}
int high = rootView.getHeight();
if (high >= rootViewHigh) {
if (mInputType != null) {
switch (mInputType) {
case Text:
setInputStyle(View.GONE, View.GONE);
break;
case Voice:
setInputStyle(View.GONE, View.VISIBLE);
break;
case Emoji:
setInputStyle(View.VISIBLE, View.GONE);
break;
}
}
rootViewHigh = 0;
}
}
}
);
emojiKeyboardLayout = activity.findViewById(R.id.emojiKeyboardLayout);
final ViewPager viewPager = (ViewPager) activity.findViewById(R.id.viewPager);
FragmentManager fragmentManager = activity.getSupportFragmentManager();
mEmojiPagerAdapter = new EmojiPagerAdapter(fragmentManager);
mMonkeyPagerAdapter = new MonkeyPagerAdapter(fragmentManager);
mZhongqiuPagerAdapter = new ZhongqiuPagerAdapter(fragmentManager);
emojiKeyboardIndicator = (LinearLayout) mActivity.findViewById(R.id.emojiKeyboardIndicator);
viewPager.setOnPageChangeListener(pageChange);
selectEmoji = mActivity.findViewById(R.id.selectEmoji);
selectEmoji.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setIndicatorCount(emojiIcons.length);
if (viewPager.getAdapter() != mEmojiPagerAdapter) {
viewPager.setAdapter(mEmojiPagerAdapter);
pageChange.resetPos();
}
setPressEmojiType(EmojiFragment.Type.Small);
}
});
selectMonkey = mActivity.findViewById(R.id.selectMonkey);
selectZhongqiu = mActivity.findViewById(R.id.selectZhongqiu);
if (emojiType == EmojiType.SmallOnly) {
selectMonkey.setVisibility(View.INVISIBLE);
mActivity.findViewById(R.id.selectMonkeyDivideLine).setVisibility(View.INVISIBLE);
selectZhongqiu.setVisibility(View.INVISIBLE);
mActivity.findViewById(R.id.selectMonkeyDivideLine1).setVisibility(View.INVISIBLE);
}
selectMonkey.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setIndicatorCount(monkeyIcons.length);
if (viewPager.getAdapter() != mMonkeyPagerAdapter) {
viewPager.setAdapter(mMonkeyPagerAdapter);
pageChange.resetPos();
}
setPressEmojiType(EmojiFragment.Type.Big);
}
});
selectZhongqiu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setIndicatorCount(zhongqiuIcons.length);
if (viewPager.getAdapter() != mZhongqiuPagerAdapter) {
viewPager.setAdapter(mZhongqiuPagerAdapter);
pageChange.resetPos();
}
setPressEmojiType(EmojiFragment.Type.Zhongqiu);
}
});
selectEmoji.performClick();
content.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
content.requestFocus();
if (commonEnterRoot != null) {
toggleSoftkeyboardWithCloseNoTextInput(mInputType);
} else {
//兼容没有使用common_enter_emoji的输入控件
emojiKeyboardLayout.setVisibility(View.GONE);
checkBoxEmoji.setChecked(false);
}
}
return false;
}
});
}
public EnterEmojiLayout(FragmentActivity activity, View.OnClickListener sendTextOnClick) {
this(activity, sendTextOnClick, Type.Default, EmojiType.Default);
}
private void setInputStyle(int emojiKeyboard, int voiceKeyboard) {
if (emojiKeyboardLayout != null) {
emojiKeyboardLayout.setVisibility(emojiKeyboard);
}
if (voiceLayout != null) {
voiceLayout.setVisibility(voiceKeyboard);
}
}
private void dropTempWindow() {
mInputBox.setVisibility(View.INVISIBLE);
ValueAnimator va = ValueAnimator.ofInt(mEnterLayoutAnimSupportContainer.softkeyboardOpenY, mEnterLayoutAnimSupportContainer.openY);
va.setDuration(300);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int y = (int) animation.getAnimatedValue();
int b = (y - mEnterLayoutAnimSupportContainer.softkeyboardOpenY) * panelHeight / (mEnterLayoutAnimSupportContainer.openY - mEnterLayoutAnimSupportContainer.softkeyboardOpenY) - panelHeight;
moveTempWindow(y);
updateEnterLayoutBottom(b);
if (y == mEnterLayoutAnimSupportContainer.openY) {
removeTempWindow();
mInputBox.setVisibility(View.VISIBLE);
}
}
});
va.start();
}
private void createTempWindow(View source) {
if (mWindowView == null) {
source.destroyDrawingCache();
source.setDrawingCacheEnabled(true);
source.buildDrawingCache();
Bitmap shot = Bitmap.createBitmap(source.getDrawingCache());
source.setDrawingCacheEnabled(false);
mWindowView = new ImageView(mActivity);
mWindowView.setImageBitmap(shot);
if (mWindowLp == null) {
mWindowLp = new WindowManager.LayoutParams();
mWindowLp.height = source.getMeasuredHeight();
mWindowLp.width = source.getMeasuredWidth();
mWindowLp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mWindowLp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowLp.format = PixelFormat.RGBA_8888;
mWindowLp.gravity = Gravity.TOP | Gravity.LEFT;
}
mWindowLp.x = source.getLeft();
mWindowLp.y = mEnterLayoutAnimSupportContainer.softkeyboardOpenY;
Log.w("softkeyboardOpenY", "" + mWindowLp.y);
mWindowManager.addView(mWindowView, mWindowLp);
} else {
removeTempWindow();
}
}
public void removeTempWindow() {
if (mWindowView != null) {
mWindowManager.removeViewImmediate(mWindowView);
mWindowView = null;
}
}
private void moveTempWindow(int y) {
mWindowLp.y = y;
mWindowManager.updateViewLayout(mWindowView, mWindowLp);
}
protected int getContentViewHeight(Activity activity) {
Rect rect = new Rect();
Window window = activity.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rect);
if (statusBarHeight == 0) {
statusBarHeight = rect.top;
}
return rect.bottom - rect.top;
}
private View getCurrentNoTextInput() {
if (mInputType != null && mInputType != InputType.Text) {
switch (mInputType) {
case Voice:
return voiceLayout;
case Emoji:
return emojiKeyboardLayout;
}
}
return null;
}
protected void toggleInputTypeWithCloseSoftkeyboard(InputType type) {
mInputType = type;
mEnterLayoutAnimSupportContainer.setCloseInputMethodBySelf(false);
Global.popSoftkeyboard(mActivity, content, false);
// mPanelLayout.setVisibility(View.GONE);
//去掉动画 不然太卡了
// createTempWindow(mInputBox);
// dropTempWindow();
}
protected void toggleSoftkeyboardWithCloseNoTextInput(InputType type) {
checkBoxEmoji.setChecked(false);
if (type != null && type != InputType.Text && mEnterLayoutStatus) {
mInputType = type;
voiceLayout.setVisibility(View.INVISIBLE);
emojiKeyboardLayout.setVisibility(View.INVISIBLE);
Global.popSoftkeyboard(mActivity, content, true);
ViewHelper.setTranslationY(emojiKeyboardLayout, 0);
ViewHelper.setTranslationY(voiceLayout, 0);
} else {
emojiKeyboardLayout.setVisibility(View.INVISIBLE);
voiceLayout.setVisibility(View.INVISIBLE);
ViewHelper.setTranslationY(emojiKeyboardLayout, 0);
ViewHelper.setTranslationY(voiceLayout, 0);
updateEnterLayoutBottom(-panelHeight);
mInputType = InputType.Text;
Global.popSoftkeyboard(mActivity, content, true);
}
}
protected void toggleNoTextInput(InputType type) {
mPanelLayout.setVisibility(View.VISIBLE);
if (type != null && type != InputType.Text) {
View dropView = getCurrentNoTextInput();
mInputType = type;
View popUpView = null;
switch (type) {
case Voice:
checkBoxEmoji.setChecked(false);
popUpView = voiceLayout;
if (!mEnterLayoutStatus) {
voiceLayout.setVisibility(View.VISIBLE);
emojiKeyboardLayout.setVisibility(View.GONE);
}
break;
case Emoji:
checkBoxEmoji.setChecked(true);
popUpView = emojiKeyboardLayout;
if (!mEnterLayoutStatus) {
emojiKeyboardLayout.setVisibility(View.VISIBLE);
voiceLayout.setVisibility(View.GONE);
}
break;
}
mEnterLayoutStatus = mEnterLayoutAnimSupportContainer.isPanelLauoutOpen();
if (mEnterLayoutStatus) {
final View dropTarget = dropView;
final View popUpTarget = popUpView;
ViewHelper.setTranslationY(popUpView, panelHeight);
ObjectAnimator drop = ObjectAnimator.ofFloat(dropView, "translationY", 0, panelHeight);
drop.setDuration(180);
drop.setInterpolator(new AccelerateInterpolator());
drop.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
dropTarget.setVisibility(View.GONE);
popUpTarget.setVisibility(View.VISIBLE);
ObjectAnimator popUp = ObjectAnimator.ofFloat(popUpTarget, "translationY", panelHeight, 0);
popUp.setDuration(180);
popUp.setInterpolator(new DecelerateInterpolator());
popUp.start();
}
});
drop.start();
} else {
popUpView.setVisibility(View.VISIBLE);
animEnterLayoutStatusChanaged(true);
}
}
}
// @Override
// public void animEnterLayoutStatusChanaged(boolean isOpen) {
// super.animEnterLayoutStatusChanaged(isOpen);
// if (!isOpen) {
// ViewHelper.setTranslationY(emojiKeyboardLayout, 0);
// ViewHelper.setTranslationY(voiceLayout, 0);
// }
// }
@Override
protected void onEnterLayoutDropDown(int bottom) {
super.onEnterLayoutDropDown(bottom);
}
@Override
protected void onEnterLayoutPopUp(int bottom) {
super.onEnterLayoutPopUp(bottom);
}
public boolean isEnterPanelShowing() {
return mEnterLayoutStatus && (emojiKeyboardLayout.getVisibility() == View.VISIBLE || voiceLayout.getVisibility() == View.VISIBLE);
}
public void closeEnterPanel() {
checkBoxEmoji.setChecked(false);
if (commonEnterRoot != null) {
if (mInputType != InputType.Voice) {
animEnterLayoutStatusChanaged(false);
}
}
}
public void openEnterPanel() {
checkBoxEmoji.setChecked(true);
checkBoxEmojiOnClicked.onClick(checkBoxEmoji);
}
@Override
public void hide() {
closeEnterPanel();
super.hide();
}
private void setIndicatorCount(int count) {
emojiKeyboardIndicator.removeAllViews();
int pointWidth = mActivity.getResources().getDimensionPixelSize(R.dimen.point_width);
int pointHeight = pointWidth;
int pointMargin = mActivity.getResources().getDimensionPixelSize(R.dimen.point_margin);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(pointWidth, pointHeight);
lp.leftMargin = pointWidth;
lp.rightMargin = pointMargin;
for (int i = 0; i < count; ++i) {
View pointView = mActivity.getLayoutInflater().inflate(R.layout.common_point, null);
emojiKeyboardIndicator.addView(pointView, lp);
}
emojiKeyboardIndicator.getChildAt(0).setBackgroundResource(R.drawable.ic_point_select);
}
private void setPressEmojiType(EmojiFragment.Type type) {
if (type == EmojiFragment.Type.Small) {
setEmojiButtonBackground(selectEmoji);
} else if (type == EmojiFragment.Type.Big) {
setEmojiButtonBackground(selectMonkey);
} else {
setEmojiButtonBackground(selectZhongqiu);
}
}
private void setEmojiButtonBackground(View view) {
final int colorNormal = 0x00000000;
final int colorPress = 0xffe8e8e8;
View[] views = new View[]{selectEmoji, selectMonkey, selectZhongqiu};
for (View item : views) {
if (view == item) {
item.setBackgroundColor(colorPress);
} else {
item.setBackgroundColor(colorNormal);
}
}
}
public enum EmojiType {
Default, SmallOnly
}
class PageChangeListener extends ViewPager.SimpleOnPageChangeListener {
int oldPos = 0;
public void resetPos() {
oldPos = 0;
}
@Override
public void onPageSelected(int position) {
View oldPoint = emojiKeyboardIndicator.getChildAt(oldPos);
View newPoint = emojiKeyboardIndicator.getChildAt(position);
oldPoint.setBackgroundResource(R.drawable.ic_point_normal);
newPoint.setBackgroundResource(R.drawable.ic_point_select);
oldPos = position;
}
}
class EmojiPagerAdapter extends FragmentStatePagerAdapter {
EmojiPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
EmojiFragment fragment = new EmojiFragment();
fragment.init(emojiIcons[i], myImageGetter, EnterEmojiLayout.this, EmojiFragment.Type.Small);
return fragment;
}
@Override
public int getCount() {
return emojiIcons.length;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
}
class MonkeyPagerAdapter extends FragmentStatePagerAdapter {
MonkeyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
EmojiFragment fragment = new EmojiFragment();
fragment.init(monkeyIcons[i], myImageGetter, EnterEmojiLayout.this, EmojiFragment.Type.Big);
return fragment;
}
@Override
public int getCount() {
return monkeyIcons.length;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
}
class ZhongqiuPagerAdapter extends FragmentStatePagerAdapter {
ZhongqiuPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
EmojiFragment fragment = new EmojiFragment();
fragment.init(zhongqiuIcons[position], myImageGetter, EnterEmojiLayout.this, EmojiFragment.Type.Zhongqiu);
return fragment;
}
@Override
public int getCount() {
return zhongqiuIcons.length;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
}
}