关于聊天面板那点事~~~软键盘和表情框切换闪跳问题!

啥也不多说,先上图

先说实现的功能:emoji表情和图片表情的显示(未实现gif表情的显示)、软键盘高度的获取、软键盘和表情面板的完美切换(不会抖动)、微信公众号键盘的展示。

该dome主要针对做im通讯的童鞋对表情实现的各种纠结给点启发。。。demo中用到了:钉钉、微信、网易中的表情图片。在这里谢谢了!如有不足或侵犯到您的权限请及时告知。谢谢!

面板布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <View
        android:layout_width="match_parent"
        android:layout_height="1.0px"
        android:background="@color/line_view_bg" />

    <RelativeLayout
        android:id="@+id/top_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/the_color_white"
        android:gravity="center"
        android:visibility="visible" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="bottom"
            android:orientation="horizontal" >

            <ImageView
                android:id="@+id/public_num_soft"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|bottom"
                android:layout_margin="10dp"
                android:src="@drawable/icon_menu_top"
                android:visibility="gone" />

            <View
                android:id="@+id/public_num_view"
                android:layout_width="1.0px"
                android:layout_height="match_parent"
                android:background="@color/layout_division_view"
                android:visibility="visible" />

            <LinearLayout
                android:id="@+id/publicNumLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:gravity="center"
                android:orientation="horizontal"
                android:visibility="gone" >

                <TextView
                    android:id="@+id/publicNumMenuTv1"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/menu_selector"
                    android:gravity="center"
                    android:padding="5dp"
                    android:textColor="@color/the_color_black"
                    android:textSize="@dimen/font_size_16sp" />

                <View
                    android:layout_width="1.0px"
                    android:layout_height="match_parent"
                    android:background="@color/layout_division_view" />

                <TextView
                    android:id="@+id/publicNumMenuTv2"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/menu_selector"
                    android:gravity="center"
                    android:padding="5dp"
                    android:textColor="@color/the_color_black"
                    android:textSize="@dimen/font_size_16sp" />

                <View
                    android:layout_width="1.0px"
                    android:layout_height="match_parent"
                    android:background="@color/layout_division_view" />

                <TextView
                    android:id="@+id/publicNumMenuTv3"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/menu_selector"
                    android:gravity="center"
                    android:padding="5dp"
                    android:textColor="@color/the_color_black"
                    android:textSize="@dimen/font_size_16sp" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/kayboadFrame"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:gravity="bottom" >

                <ImageView
                    android:id="@+id/audio_switch_btn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="bottom"
                    android:layout_margin="3dp"
                    android:src="@drawable/talk_detail_audio_btn" />

                <RelativeLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_weight="1" >

                    <LinearLayout
                        android:id="@+id/edit_view"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_centerVertical="true"
                        android:layout_margin="2dp" >

                        <RelativeLayout
                            android:layout_width="0dp"
                            android:layout_height="wrap_content"
                            android:layout_weight="1"
                            android:orientation="horizontal" >

                            <com.qyx.android.weight.edittext.EmojisEditText
                                android:id="@+id/editText"
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:background="@drawable/edittext_bg"
                                android:maxHeight="200dp"
                                android:maxLines="4"
                                android:minHeight="35dp"
                                android:paddingBottom="3dp"
                                android:paddingRight="35dp"
                                android:textColor="@color/the_color_black"
                                android:textColorHint="@color/the_color_black"
                                android:textCursorDrawable="@drawable/color_cursor"
                                android:textSize="@dimen/font_size_14sp" />

                            <ImageView
                                android:id="@+id/action_show_emoji_panel"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_alignBottom="@id/editText"
                                android:layout_alignRight="@id/editText"
                                android:layout_marginBottom="5dp"
                                android:src="@drawable/emoji" />
                        </RelativeLayout>

                        <TextView
                            android:id="@+id/send_btn"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="bottom"
                            android:layout_marginBottom="2dp"
                            android:layout_marginLeft="5dip"
                            android:background="@color/the_color_blue"
                            android:gravity="center"
                            android:paddingBottom="6dp"
                            android:paddingLeft="8dp"
                            android:paddingRight="8dp"
                            android:paddingTop="6dp"
                            android:text="@string/sent"
                            android:textColor="@color/the_color_white"
                            android:textSize="@dimen/font_size_14sp"
                            android:visibility="gone" />
                    </LinearLayout>

                    <Button
                        android:id="@+id/sendAudio"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_centerVertical="true"
                        android:background="@drawable/button_audio_bg"
                        android:gravity="center"
                        android:padding="6dp"
                        android:text="@string/press_talk"
                        android:textColor="@color/the_color_normal"
                        android:textSize="@dimen/font_size_18sp"
                        android:visibility="gone" />
                </RelativeLayout>

                <ImageView
                    android:id="@+id/addMoreBtn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="bottom"
                    android:layout_marginBottom="2dp"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="5dp"
                    android:src="@drawable/talk_detail_add_btn" />
            </LinearLayout>
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1.0px"
            android:background="@color/layout_division_view" />
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1.0px"
        android:background="@color/layout_division_view" />

    <RelativeLayout
        android:id="@+id/action_view"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        android:background="@color/the_color_white"
        android:visibility="gone" >

        <LinearLayout
            android:id="@+id/emoji_action"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:visibility="gone" >

            <LinearLayout
                android:id="@+id/content_view"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="vertical" >

                <android.support.v4.view.ViewPager
                    android:id="@+id/gif_list"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_gravity="center"
                    android:layout_weight="1" />

                <LinearLayout
                    android:id="@+id/points_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginBottom="5dp"
                    android:orientation="horizontal" >

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/point" />
                </LinearLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >

                <View
                    android:id="@+id/view"
                    android:layout_width="match_parent"
                    android:layout_height="1.0px"
                    android:background="@color/layout_division_view" />

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" >

                    <ImageView
                        android:id="@+id/emoji_add_iv"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentLeft="true"
                        android:layout_centerInParent="true"
                        android:paddingLeft="20dp"
                        android:paddingRight="20dp"
                        android:src="@drawable/icon_emoji_add" />

                    <ImageView
                        android:id="@+id/emoji_setting_iv"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentRight="true"
                        android:layout_centerInParent="true"
                        android:paddingLeft="20dp"
                        android:paddingRight="20dp"
                        android:src="@drawable/icon_emoji_setting" />

                    <android.support.v7.widget.RecyclerView
                        android:id="@+id/recyclerview_horizontal"
                        android:layout_width="match_parent"
                        android:layout_height="35dp"
                        android:layout_toLeftOf="@id/emoji_setting_iv"
                        android:layout_toRightOf="@id/emoji_add_iv"
                        android:scrollbars="none" />
                </RelativeLayout>
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/more_actions"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:orientation="vertical"
            android:visibility="gone" >

            <android.support.v4.view.ViewPager
                android:id="@+id/more_list_viewpager"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_gravity="center"
                android:layout_weight="1" />

            <LinearLayout
                android:id="@+id/more_points_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="5dp"
                android:orientation="horizontal" >

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/point" />
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>

Activity布局页面引入面板布局:

<com.test.emoji.face.panel.ResizeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/messagelist"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/page_bg_normal" >

    <TextView
        android:id="@+id/gif_view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="@string/hide_soft"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:background="@color/the_color_gray"
        android:textColor="@color/the_color_black"
        android:layout_marginBottom="50dp"
        android:visibility="visible" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/gif_view"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/msg_listView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:cacheColorHint="@android:color/transparent"
            android:divider="@null"
            android:listSelector="@android:color/transparent"
            android:visibility="visible" />

        <include
            android:id="@+id/face_panel"
            layout="@layout/face_panel_layout" />
    </LinearLayout>

</com.test.emoji.face.panel.ResizeLayout>

布局中ResizeLayout是用来计算软键盘高度的View,一下是ResizeLayout的源码:

public class ResizeLayout extends RelativeLayout {

	private OnResizeListener mListener;

	public interface OnResizeListener {
		void OnResize(int w, int h, int oldw, int oldh);
	}

	public void setOnResizeListener(OnResizeListener l) {
		mListener = l;
	}

	public ResizeLayout(Context context) {
		super(context);
	}

	public ResizeLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public ResizeLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);

		if (mListener != null) {
			mListener.OnResize(w, h, oldw, oldh);
		}
	}
}

以上是布局文件。下面来看面板逻辑的实现。

以下这个类很重要,他主要实现了面板和软键盘的切换和软键盘的高度计算,以及面板中表情的显示和面板中控件的点击回调等。(程序猿组织语言能力欠佳,还是看源码吧

public class FacePanelManager {

	/**
	 * 计算软键盘高度
	 */
	private ResizeLayout mResizeLayout;
	private ViewPager gif_list, moreViewPager;
	private RecyclerView listView;
	private BottomEmojiAdapter mBottomEmojiAdapter;
	private LinearLayout indexGroup, moreIndexGroup;
	private GifAdapter mAdapter = null;
	private EmojiAdapter emojiAdapter = null;
	private CheckEmojiEntity selectedCheckEmoji = null;
	private ArrayList<CheckEmojiEntity> arrayList = null;
	private boolean flag;
	private int keyboardHeight = 0;
	/***
	 * 底部布局
	 */
	private View action_view;
	private InputMethodManager inputManager;
	private EditText sendEdit;
	/**
	 * emojiBtn:表情按钮 ,addMoreBtn:更多按钮,audioBtn:语音按钮,publicNumSoft:公众号按钮
	 */
	private ImageView emojiBtn, addMoreBtn, audioBtn, publicNumSoft;
	/**
	 * 发送消息按钮
	 */
	private TextView send;
	/**
	 * 发送语音按钮
	 */
	private Button sendAudioButton;
	/**
	 *
	 */
	private LinearLayout editView;
	/**
	 * 更多布局
	 */
	private LinearLayout more_actions, emoji_action;
	/**
	 * 公众号textview
	 */
	private TextView publicNumMenuTv1, publicNumMenuTv2, publicNumMenuTv3;
	private View public_num_view;
	/**
	 * 公众号布局和输入框布局
	 */
	private LinearLayout publicNumLayout, kayboadFrameLayout;

	private ISendAudioListener mSendAudioListener = null;
	private ISendTextListener mSendTextListener = null;
	private ISendGifListener mISendGifListener = null;
	private ISendHideFacePanel mISendHideFacePanel = null;
	private Context mContext;
	private PanelMoreManager mPanelMoreManager;
	private PanelPublicNumManager mPanelPublicNumManager;
	private boolean isShowPublicNumSoft = false;

	/**
	 * 面板管理
	 *
	 * @param _Context
	 * @param view
	 *            面板布局
	 * @param _recordView
	 *            录音布局
	 * @param _ResizeLayout
	 *            获取软键盘高度
	 * @param is_show_public_num_soft
	 *            是否显示公众号软键盘
	 */
	public FacePanelManager(Context _Context, View view,
			ResizeLayout _ResizeLayout, boolean is_show_public_num_soft) {
		isShowPublicNumSoft = is_show_public_num_soft;
		mResizeLayout = _ResizeLayout;
		mContext = _Context;
		initView(view);
		mPanelMoreManager = new PanelMoreManager(moreIndexGroup, moreViewPager,
				mContext);
		mPanelPublicNumManager = new PanelPublicNumManager(_Context,
				kayboadFrameLayout, publicNumLayout, publicNumSoft,
				public_num_view, publicNumMenuTv1, publicNumMenuTv2,
				publicNumMenuTv3, new ISendPublicNumOnClick() {

					@Override
					public void onPublicNumClick(String url) {
						Toast.makeText(mContext, url, Toast.LENGTH_SHORT)
								.show();
					}
				});
	}

	// 初始化控件
	private void initView(View view) {

		inputManager = (InputMethodManager) mContext
				.getSystemService(Context.INPUT_METHOD_SERVICE);
		emojiBtn = (ImageView) view.findViewById(R.id.action_show_emoji_panel);

		action_view = view.findViewById(R.id.action_view);
		addMoreBtn = (ImageView) view.findViewById(R.id.addMoreBtn);
		audioBtn = (ImageView) view.findViewById(R.id.audio_switch_btn);

		gif_list = (ViewPager) view.findViewById(R.id.gif_list);
		moreViewPager = (ViewPager) view.findViewById(R.id.more_list_viewpager);
		indexGroup = (LinearLayout) view.findViewById(R.id.points_view);
		moreIndexGroup = (LinearLayout) view
				.findViewById(R.id.more_points_view);
		mResizeLayout.setOnResizeListener(resizeListener);
		sendEdit = (EditText) view.findViewById(R.id.editText);
		send = (TextView) view.findViewById(R.id.send_btn);
		more_actions = (LinearLayout) view.findViewById(R.id.more_actions);
		emoji_action = (LinearLayout) view.findViewById(R.id.emoji_action);
		editView = (LinearLayout) view.findViewById(R.id.edit_view);
		sendAudioButton = (Button) view
				.findViewById(R.id.sendAudio);
		/**
		 * 公众号
		 */
		publicNumSoft = (ImageView) view.findViewById(R.id.public_num_soft);
		publicNumMenuTv1 = (TextView) view.findViewById(R.id.publicNumMenuTv1);
		publicNumMenuTv2 = (TextView) view.findViewById(R.id.publicNumMenuTv2);
		publicNumMenuTv3 = (TextView) view.findViewById(R.id.publicNumMenuTv3);

		publicNumLayout = (LinearLayout) view
				.findViewById(R.id.publicNumLayout);
		kayboadFrameLayout = (LinearLayout) view
				.findViewById(R.id.kayboadFrame);
		public_num_view = view.findViewById(R.id.public_num_view);

		initHorizaontal(view);
	}

	public void initListener() {
		emojiBtn.setOnClickListener(clickListener);
		addMoreBtn.setOnClickListener(clickListener);

		/** 内容编辑框事件 **/
		sendEdit.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showSoftKeyboard();
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				sendEdit.setFocusable(true);
				sendEdit.setFocusableInTouchMode(true);
				sendEdit.requestFocus();
				setActionViewDisplay(1);
				emojiBtn.setImageResource(R.drawable.emoji);
			}
		});
		sendEdit.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				if (TextUtils.isEmpty(s)
						|| TextUtils.isEmpty(sendEdit.getText().toString()
								.trim())) {
					send.setVisibility(View.GONE);
					addMoreBtn.setVisibility(View.VISIBLE);
					return;
				}
				if (count <= 0) {
					return;
				}

				/** 控制发送按钮和更多按钮的显示和隐藏 **/
				if (sendEdit.getText().toString().trim().length() > 0) {
					send.setVisibility(View.VISIBLE);
					addMoreBtn.setVisibility(View.GONE);
				} else {
					send.setVisibility(View.GONE);
					addMoreBtn.setVisibility(View.VISIBLE);
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}

			@Override
			public void afterTextChanged(Editable s) {
			}
		});
		send.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String content = sendEdit.getText().toString();
				if (mSendTextListener != null) {
					mSendTextListener.onSendTextContent(content);
				}
				sendEdit.setText("");
			}
		});

		/********* 语音按钮操作 ************/
		audioBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				/** 隐藏编辑框、显示发送语音按钮 **/
				if (sendAudioButton.getVisibility() == View.GONE) {
					editView.setVisibility(View.GONE);
					sendAudioButton.setVisibility(View.VISIBLE);
					audioBtn.setImageResource(R.drawable.talk_detail_keyboard_btn);
					hideSoftKeyboard();
					// actionView.setVisibility(View.GONE);
					setActionViewDisplay(1);
				} else {
					/** 显示编辑框、隐藏发送语音按钮 **/
					editView.setVisibility(View.VISIBLE);
					sendAudioButton.setVisibility(View.GONE);
					emojiBtn.setImageResource(R.drawable.emoji);
					audioBtn.setImageResource(R.drawable.talk_detail_audio_btn);
					sendEdit.setFocusable(true);
					sendEdit.setFocusableInTouchMode(true);
					sendEdit.requestFocus();
					showSoftKeyboard();
				}
				emojiBtn.setBackgroundResource(R.drawable.emoji);
			}
		});

		/** 公众号和标签输入框切换 **/
		publicNumSoft.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if (kayboadFrameLayout.getVisibility() == View.VISIBLE) {
					// TODO
					kayboadFrameLayout.setVisibility(View.GONE);
					publicNumLayout.setVisibility(View.VISIBLE);
					publicNumSoft.setImageResource(R.drawable.icon_menu_top);
				} else {
					kayboadFrameLayout.setVisibility(View.VISIBLE);
					publicNumLayout.setVisibility(View.GONE);
					publicNumSoft.setImageResource(R.drawable.icon_menu_bottom);
				}
				sendEdit.setFocusable(true);
				sendEdit.setFocusableInTouchMode(true);
				sendEdit.requestFocus();
				emojiBtn.setBackgroundResource(R.drawable.emoji);
				setActionViewDisplay(1);
				inputManager.hideSoftInputFromWindow(sendEdit.getWindowToken(),
						0);
			}
		});

		if (isShowPublicNumSoft) {
			publicNumSoft.setVisibility(View.VISIBLE);
			publicNumLayout.setVisibility(View.VISIBLE);
		}
	}

	private void initHorizaontal(View view) {
		listView = (RecyclerView) view
				.findViewById(R.id.recyclerview_horizontal);
		// 创建一个线性布局管理器
		LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
		layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
		// 设置布局管理器
		listView.setLayoutManager(layoutManager);
		getData();
	}

	private void getData() {
		arrayList = new ArrayList<CheckEmojiEntity>();
		CheckEmojiEntity mCheckEmojiEntity1 = new CheckEmojiEntity(1,
				R.drawable.ajmd_s_pressed, "ajmd");
		CheckEmojiEntity mCheckEmojiEntity2 = new CheckEmojiEntity(2,
				R.drawable.icon_tusiji, "tusiji");
		CheckEmojiEntity mCheckEmojiEntity3 = new CheckEmojiEntity(3,
				R.drawable.xxy_s_pressed, "hb");
		CheckEmojiEntity mCheckEmojiEntity4 = new CheckEmojiEntity(4,
				R.drawable.xxy_s_pressed, "bu");
		arrayList.add(mCheckEmojiEntity1);
		arrayList.add(mCheckEmojiEntity2);
		arrayList.add(mCheckEmojiEntity3);
		arrayList.add(mCheckEmojiEntity4);
		// 设置emoji表情在第一个
		arrayList.add(0, new CheckEmojiEntity(-1, -1, ""));
		mBottomEmojiAdapter = new BottomEmojiAdapter(mContext, arrayList,
				new IOnItemClick() {

					@Override
					public void onItemClick(CheckEmojiEntity mCheckEmojiEntity) {
						if (mCheckEmojiEntity != null) {
							if (selectedCheckEmoji == mCheckEmojiEntity) {
								return;
							} else {
								selectedCheckEmoji = mCheckEmojiEntity;
							}
							flag = true;
							mBottomEmojiAdapter
									.setSelectedItem(mCheckEmojiEntity.id);
							if (mCheckEmojiEntity.id == -1
									&& mCheckEmojiEntity.resourceId == -1
									&& TextUtils
											.isEmpty(mCheckEmojiEntity.resourceName)) {
								showIndexMark(0, 1,
										mCheckEmojiEntity.resourceName);
							} else {
								showIndexMark(0, 2,
										mCheckEmojiEntity.resourceName);
							}
						}
					}
				});
		listView.setAdapter(mBottomEmojiAdapter);
		// 设置默认值
		showIndexMark(0, 1, "");
		selectedCheckEmoji = arrayList.get(0);
		mBottomEmojiAdapter.setSelectedItem(selectedCheckEmoji.id);
	}

	/**
	 * 表情按钮和更多按钮点击事件
	 */
	private final View.OnClickListener clickListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			sendEdit.setFocusable(true);
			sendEdit.setFocusableInTouchMode(true);
			sendEdit.requestFocus();
			if (v == emojiBtn) {
				if (action_view.getVisibility() == View.VISIBLE) {
					if (more_actions.getVisibility() == View.VISIBLE) {
						more_actions.setVisibility(View.GONE);
						emoji_action.setVisibility(View.VISIBLE);
						emojiBtn.setImageResource(R.drawable.ic_emoji_selector);
						return;
					}
					showSoftKeyboard();
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					setActionViewDisplay(1);
					emojiBtn.setBackgroundResource(R.drawable.emoji);
				} else {
					hideSoftKeyboard();
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					setActionViewDisplay(2);
					emoji_action.setVisibility(View.VISIBLE);
					emojiBtn.setImageResource(R.drawable.ic_emoji_selector);
				}
			} else if (v == addMoreBtn) {
				editView.setVisibility(View.VISIBLE);
				sendAudioButton.setVisibility(View.GONE);
				emoji_action.setVisibility(View.GONE);
				emojiBtn.setImageResource(R.drawable.emoji);
				audioBtn.setImageResource(R.drawable.talk_detail_audio_btn);

				if (action_view.getVisibility() == View.VISIBLE) {
					// 更多布局已经显示
					if (more_actions.getVisibility() == View.VISIBLE) {
						showSoftKeyboard();
						try {
							Thread.sleep(200);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						setActionViewDisplay(1);
						more_actions.setVisibility(View.GONE);
					} else {
						// 更多布局未显示
						hideSoftKeyboard();
						more_actions.setVisibility(View.VISIBLE);
						emoji_action.setVisibility(View.GONE);
					}
				} else {
					hideSoftKeyboard();
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					setActionViewDisplay(2);
					more_actions.setVisibility(View.VISIBLE);
					// showBottomView(1);
					// scrollToEnd();
				}
			}

		}

	};

	/**
	 * 显示emoji或者gif标点
	 *
	 * @param index
	 * @param file_type_name
	 */
	private void showIndexMark(int index, int type, String file_type_name) {
		if (index == 0 && type == 2) {
			initViewPageData(file_type_name);
		} else if (index == 0 && type == 1) {
			initEmojiViewPageData();
		}
		if (type == 2) {
			if (mAdapter == null)
				return;
		} else if (type == 1) {
			if (emojiAdapter == null) {
				return;
			}
		}
		int max = 0;
		if (type == 1) {
			max = emojiAdapter.getCount();
		} else {
			max = mAdapter.getCount();
		}
		indexGroup.removeAllViews();
		for (int i = 0; i < max; i++) {
			ImageView image = new ImageView(mContext);
			LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			lp.leftMargin = 10;
			lp.rightMargin = 10;
			lp.topMargin = 5;
			lp.bottomMargin = 5;
			if (index == i) {
				image.setImageResource(R.drawable.point_selected);
			} else {
				image.setImageResource(R.drawable.point);
			}
			image.setLayoutParams(lp);
			indexGroup.addView(image);
		}

	}

	/**
	 * 初始化emoji事件
	 */
	private void initEmojiViewPageData() {
		emojiAdapter = new EmojiAdapter(mContext, new OnEmojiSelected() {
			@Override
			public void onEmojiSelected(Emoji emoji) {
				if (TextUtils.isEmpty(emoji.text)) {
					return;
				}

				int index = sendEdit.getSelectionStart();
				String text = sendEdit.getText().toString();
				String startString = text.substring(0, index);
				String endString = text.substring(index, text.length());
				String emojiText = "[" + emoji.text + "] ";

				sendEdit.setFocusable(true);
				sendEdit.setFocusableInTouchMode(true);
				sendEdit.requestFocus();
				sendEdit.setText(startString + emojiText + endString);
				sendEdit.setSelection(index + emojiText.length());
			}

			@Override
			public void onEmojiDeleted(Emoji emoji) {
				QyxEmoji.deleteEmoji(sendEdit, emoji.text);
			}
		});
		gif_list.setAdapter(emojiAdapter);
		initViewPageLisenter(1, "");
	}

	/**
	 * 初始化viewpage数据
	 *
	 * @param file_type_name
	 *            显示表情的所在文件夹的目录
	 */
	private void initViewPageData(final String file_type_name) {
		mAdapter = new GifAdapter(mContext, file_type_name,
				new OnBuildInViewGifSelected() {

					@Override
					public void onGifSelected(ViewGif mGif) {
						if (mISendGifListener != null) {
							mISendGifListener.onSendGif(mGif.file_type_name);
						}
						// gif_view.setAsyncCacheImage(mGif.file_type_name);
					}
				});
		gif_list.setAdapter(mAdapter);
		initViewPageLisenter(2, file_type_name);
	}

	/**
	 * 注册ViewPage滑动事件
	 *
	 * @param type
	 *            1:emoji2:gif
	 * @param file_type_name
	 *            1:“”2:gif类型名称
	 */
	private void initViewPageLisenter(final int type,
			final String file_type_name) {
		gif_list.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int index) {
				showIndexMark(index, type, file_type_name);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int arg0) {
				/** 设置viewpage滑动到最后一页和第一页的时切换其他类型Gif表情 **/
				switch (arg0) {
				case ViewPager.SCROLL_STATE_DRAGGING:
					flag = false;
					break;
				case ViewPager.SCROLL_STATE_SETTLING:
					flag = true;
					break;
				case ViewPager.SCROLL_STATE_IDLE:
					if (gif_list.getCurrentItem() == gif_list.getAdapter()
							.getCount() - 1 && !flag) {
						showLastGif();
					} else if (gif_list.getCurrentItem() == 0 && !flag) {
						showPreviousGif();
					}
					flag = true;
					break;
				}
			}
		});
	}

	/**
	 * 显示下一个GifViewPage
	 */
	private void showLastGif() {
		if (selectedCheckEmoji != null && arrayList != null
				&& arrayList.size() > 0) {
			for (int i = 0, size = arrayList.size(); i < size; i++) {
				if (selectedCheckEmoji == arrayList.get(i)
						&& i < arrayList.size() - 1) {
					// 显示下一个GifViewPage
					int lastIndex = ++i;
					if (lastIndex >= arrayList.size()) {
						return;
					}
					/** 选中第一个item **/
					showIndexMark(0, 2, arrayList.get(lastIndex).resourceName);
					/** 设置当前选中的gif类型 **/
					selectedCheckEmoji = arrayList.get(lastIndex);
					/** 修改选中的表情背景 **/
					mBottomEmojiAdapter.setSelectedItem(arrayList
							.get(lastIndex).id);

					listView.scrollToPosition(lastIndex);
					break;
				}
			}
		}
	}

	/**
	 * 显示上个gifViewPage(默认选中上一个gif表情的最后一个item)
	 */
	private void showPreviousGif() {
		if (selectedCheckEmoji != null && arrayList != null
				&& arrayList.size() > 0) {
			for (int i = 0, size = arrayList.size(); i < size; i++) {
				if (selectedCheckEmoji == arrayList.get(i) && i != 0) {
					// 显示上一个GifViewPage
					int previousIndex = --i;
					if (previousIndex >= arrayList.size() || previousIndex < 0) {
						return;
					}
					int type = 0;
					if (previousIndex == 0) {
						// 第一页 显示emoji表情
						type = 1;
					} else {
						type = 2;
					}

					/** 选中最后一个item **/
					showIndexMark(0, type,
							arrayList.get(previousIndex).resourceName);
					/** 选中最后一个item **/
					if (gif_list != null) {
						int count = 0;
						if (previousIndex == 0) {
							// 第一页 显示emoji表情
							count = emojiAdapter.getCount() - 1;
						} else {
							count = mAdapter.getCount() - 1;
						}
						gif_list.setCurrentItem(count);
					}
					/** 设置当前选中的gif类型 **/
					selectedCheckEmoji = arrayList.get(previousIndex);
					/** 修改选中的表情背景 **/
					mBottomEmojiAdapter.setSelectedItem(arrayList
							.get(previousIndex).id);
					listView.scrollToPosition(previousIndex);
					break;
				}
			}
		}
	}

	/**
	 * 初始化更多数据
	 */
	public void initMoreAdapter(ArrayList<MoreEntity> _ArrayList,
			IMoreOnClickListener mIMoreOnClickListener) {
		mPanelMoreManager.initMoreAdapter(_ArrayList, mIMoreOnClickListener);
	}

	/**
	 * 设置底部view显示隐藏状态
	 *
	 * @param type
	 */
	private void setActionViewDisplay(int type) {
		if (action_view != null) {
			if (type == 1) {
				action_view.setVisibility(View.GONE);
				more_actions.setVisibility(View.GONE);
				emoji_action.setVisibility(View.GONE);
				emojiBtn.setImageResource(R.drawable.emoji);
			} else {
				action_view.setVisibility(View.VISIBLE);
			}
		}
	}

	private void showSoftKeyboard() {
		((Activity) mContext).getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

		inputManager
				.showSoftInput(sendEdit, InputMethodManager.HIDE_NOT_ALWAYS);
	}

	private void hideSoftKeyboard() {
		((Activity) mContext).getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

		if (inputManager.isActive()) {
			inputManager.hideSoftInputFromWindow(sendEdit.getWindowToken(), 0);
		}
	}

	/**
	 * 控制软键盘高度
	 */
	private ResizeLayout.OnResizeListener resizeListener = new ResizeLayout.OnResizeListener() {

		@Override
		public void OnResize(int w, int h, int oldw, int oldh) {
			if (oldw != 0 && oldh != 0) {
				if (h < oldh) {
					keyboardHeight = oldh - h;
					keyboardHeight = Math.max(dip2px(mContext, 240),
							keyboardHeight);
					setFaceActionViewHeight();
				}
			}
		}
	};

	/**
	 * 设置面板高度
	 *
	 * @param keyboardHeight
	 */
	private void setFaceActionViewHeight() {
		LayoutParams faceParams = action_view.getLayoutParams();
		faceParams.height = keyboardHeight;
		action_view.setLayoutParams(faceParams);
	}

	/**
	 * 把dip值转换成px值
	 */
	private int dip2px(Context context, float dipValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dipValue * scale + 0.5f);
	}

	public void hideFacePanel() {

	}

	/**
	 * 监听录音返回
	 *
	 * @param _SendAudioListener
	 */
	public void onSendAudioListener(ISendAudioListener _SendAudioListener) {
		mSendAudioListener = _SendAudioListener;
	}

	/**
	 * 发送按钮监听
	 *
	 * @param _SendTextListener
	 */
	public void onSendTextListener(ISendTextListener _SendTextListener) {
		mSendTextListener = _SendTextListener;
	}

	/**
	 * 发送gif监听
	 *
	 * @param _SendGifListener
	 */
	public void onSendGifListener(ISendGifListener _SendGifListener) {
		mISendGifListener = _SendGifListener;
	}

	/**
	 * 设置不显示面板
	 *
	 * @param _HideFacePanel
	 */
	public void onSendHideFacePanel(ISendHideFacePanel _HideFacePanel) {
		mISendHideFacePanel = _HideFacePanel;

		mISendHideFacePanel.onHideFacePanel(new IHideFacePanel() {

			@Override
			public void hideFacePanel() {
				hideSoftKeyboard();
				setActionViewDisplay(1);
			}
		});
	}

	/**
	 * 设置公众号数据
	 *
	 * @param arrayList
	 */
	public void setPublicNumData(ArrayList<PublicNumMenu> arrayList) {
		if (isShowPublicNumSoft) {
			mPanelPublicNumManager.setPublicNumMenu(arrayList);
		}
	}
}

以上就是面板的主要实现了。。。接下来就是如何调用这个面板啦!其实很简单。只需传入面板的布局和是否控制公众号键盘的显示和公众号数据。其他的事件点击会回调给Activity(面板中只处理了一些事件的回调。)一下是调用面板:

public class MainActivity extends Activity {
	private ResizeLayout mResizeLayout;
	private IHideFacePanel hideFacePanel;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mResizeLayout = (ResizeLayout) findViewById(R.id.messagelist);
		initFacePanelView();
		findViewById(R.id.gif_view).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				hideFacePanel.hideFacePanel();
			}
		});
	}

	/**
	 * 模拟公众号数据
	 * @return
	 */
	private ArrayList<PublicNumMenu> getPublicNumData() {
		ArrayList<PublicNumMenu> arrayList = new ArrayList<PublicNumMenu>();
		PublicNumMenu menu = new PublicNumMenu();
		menu.text = "第一个";
		menu.url = "http://www.baidu.com";

		PublicNumMenu menu2 = new PublicNumMenu();
		menu2.text = "第二个";
		menu2.url = "http://www.baidu.com";
		menu2.arrayList = getPublicNumData1();

		PublicNumMenu menu3 = new PublicNumMenu();
		menu3.text = "第三个";
		menu3.url = "http://www.baidu.com";
		arrayList.add(menu);
		arrayList.add(menu2);
		arrayList.add(menu3);

		return arrayList;
	}

	private ArrayList<PublicNumMenu> getPublicNumData1() {
		ArrayList<PublicNumMenu> arrayList = new ArrayList<PublicNumMenu>();
		PublicNumMenu menu = new PublicNumMenu();
		menu.text = "第一个";
		menu.url = "http://www.baidu.com";

		PublicNumMenu menu2 = new PublicNumMenu();
		menu2.text = "第二个回火是";
		menu2.url = "http://www.baidu.com";

		PublicNumMenu menu3 = new PublicNumMenu();
		menu3.text = "第三个";
		menu3.url = "http://www.baidu.com";
		arrayList.add(menu);
		arrayList.add(menu2);
		arrayList.add(menu3);
		return arrayList;
	}
	private void initFacePanelView() {
		View view = findViewById(R.id.face_panel);

		/**最后一个参数是控制是否显示公众号键盘**/
		FacePanelManager facePanelManager = new FacePanelManager(this, view,
				 mResizeLayout, false);
		facePanelManager.initListener();
		facePanelManager.setPublicNumData(getPublicNumData());

		/**点击加号的时候回调**/
		facePanelManager.initMoreAdapter(PanelMoreManager.getPanelMoreData(2),
				new IMoreOnClickListener() {

					@Override
					public void onMoreClick(int type) {
						// TODO
						Toast.makeText(MainActivity.this, "更多模块item的点击" + type,
								Toast.LENGTH_SHORT).show();
					}
				});

		facePanelManager.onSendAudioListener(new ISendAudioListener() {

			@Override
			public void onAudioFilePath(String audioPath) {
				Toast.makeText(MainActivity.this, "发送语音" + audioPath,
						Toast.LENGTH_SHORT).show();
			}
		});

		facePanelManager.onSendGifListener(new ISendGifListener() {

			@Override
			public void onSendGif(String gifName) {
				Toast.makeText(MainActivity.this, "点击了某个gif表情:" + gifName,
						Toast.LENGTH_SHORT).show();
			}
		});
		facePanelManager.onSendTextListener(new ISendTextListener() {

			@Override
			public void onSendTextContent(String editContent) {
				Toast.makeText(MainActivity.this, "点击了发送按钮" + editContent,
						Toast.LENGTH_SHORT).show();
			}
		});

		facePanelManager.onSendHideFacePanel(new ISendHideFacePanel() {

			@Override
			public void onHideFacePanel(IHideFacePanel mHideFacePanel) {
				//通知面板、隐藏软键盘和面板
				hideFacePanel = mHideFacePanel;
			}
		});
	}
}

好了。。。就写在这里吧!大家有啥不明白的直接问我吧!(Q:2473471081)

源码地址:http://download.csdn.net/detail/songneng1993/9490995

时间: 2024-10-07 17:24:02

关于聊天面板那点事~~~软键盘和表情框切换闪跳问题!的相关文章

Android动态改变布局,比如登陆弹出软键盘,登陆框上移(转载)

Android动态改变布局 http://www.cnblogs.com/angeldevil/p/3836256.html 遇到这么个需求,先看图:      其实是一个软件的登录界面,初始是第一个图的样子,当软键盘弹出后变为第二个图的样子,因为登录界面有用户名.密码.登录按钮,不这样的话软键盘弹出后会遮住登录按钮(其实之前的实现放到了ScrollView里面,监听软键盘弹出后滚动到底部,软键盘隐藏后滚动到顶部,也是可以的). 最简单的方法就是多加几个冗余的View,根据软键盘的状态隐藏不需要

android自动弹出软键盘(输入键盘)

searchEditView.setFocusable(true); searchEditView.setFocusableInTouchMode(true); searchEditView.requestFocus(); Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { InputMethodManager inputManager = (InputMethodManager) sea

[转]android自动弹出软键盘(输入键盘)

转自:http://www.devdiv.com/home.php?mod=space&uid=65729&do=blog&id=11847 很多应用中对于一个界面比如进入搜索界面或者修改信息等等情况,为了用户体验应该自动弹出软键盘而不是让用户主动点击输入框才弹出(因为用户进入该界面必然是为了更改信息).具体实现这种效果如下: [代码]java代码: 1 EditText editText.setFocusable(true); 2 editText.setFocusableInT

软键盘 输入法管理器 InputMethodManager

 基本介绍 软键盘的显示原理 软键盘其实是一个Dialog.InputMethodService为我们的输入法创建了一个Dialog,并且对某些参数进行了设置,使之能够在底部或者全屏显示.当我们点击输入框时,系统会对当前的主窗口进行调整,以便留出相应的空间来显示该Dialog在底部,或者全屏. 控制活动主窗口调整方式 Android定义了一个属性windowSoftInputMode,用它可以让程序控制活动主窗口调整的方式.我们可以在配置文件AndroidManifet.xml中对Activit

Android 软键盘

一些重要常量含义: HIDE_IMPLICIT_ONLY     常量值: 1 (0x00000001) hideSoftInputFromWindow(IBinder, int)中的标志,表示如果用户未显式地显示软键盘窗口,则隐藏窗口. HIDE_NOT_ALWAYS         常量值: 2 (0x00000002) hideSoftInputFromWindow(IBinder, int)中的标志,表示软键盘窗口总是隐藏,除非开始时以SHOW_FORCED显示. RESULT_HIDD

android显示和隐藏软键盘

显示键盘: EditText editText.setFocusable(true); editText.setFocusableInTouchMode(true); editText.requestFocus(); InputMethodManager inputManager = (InputMethodManager)editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.show

activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性。

android:windowSoftInputMode 这个属性能影响两件事情: [一]当有焦点产生时,软键盘是隐藏还是显示 [二]是否减少活动主窗口大小以便腾出空间放软键盘 它的设置必须是下面列表中的一个值,或一个"state-"值加一个"adjust-"值的组合.在任一组设置多个值--多个"state-"values,例如&mdash有未定义的结果.各个值之间用|分开.例如:<activity android:windowSof

activity中界面中edittext自动获取焦点(软键盘弹出)解决

最近在做开发的时候遇到个比较烦的问题就是 我的某个activity页面中有editText,在一进去就会调用软键盘,这样看起来不美观,所以看了下api http://developer.android.com/guide/topics/manifest/activity-element.html(要翻墙) 在<Activity>节点下也就是在manifest文件的配置activity节点的时候需要配置 android:windowSoftInputMode 这个属性来控制软键盘的模式.我摘录了

Android软键盘弹出时布局问题

最近项目需要做一个类似聊天室的模块,基于Socket实现的,这部分稍后一段时间再做总结,功能上的相关点都实现了小例子也做出来了,最后发现一个比较腻歪的问题就是软键盘弹出时总是会把标题“挤出”屏幕,(无论标题是写在布局中还是仿照theme的方式添加到style中),输入时有失观赏如下图:      隐隐感觉之前项目一直有类似问题,只不过一般只在登陆界面,无伤大雅,用户输入后一掠而过,可以忽略,但这个页面这么处理确实不太美观. 查了下此类问题大致两种思路解决:         一.调整布局在底层使用