导语
有时候,我们项目中的需求如下图
整个界面我们可以就理解为两个部分,上面部分是一个ListView,下面是一个自定义VewGroup,这个ViewGroup包装了底部的所有控件。下面我们重点讲解如何包装底部
先上代码
(一)继承RelativeLayout的ChatInput类:
package com.weplaykit.sdk.module.person.view.widget;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.weplaykit.sdk.common.WPKApplication;
import com.weplaykit.sdk.module.person.contract.PrivateMsgDetailContract;
import com.weplaykit.sdk.thirdparty.emojicon.EmojiconEditText;
import com.weplaykit.sdk.util.MR;
import com.weplaykit.sdk.util.SoftKeyboardUtil;
import com.weplaykit.sdk.widget.EmojiSelectView;
import static com.weplaykit.sdk.module.person.view.widget.ChatInput.PanelState.ISALLUNSEE;
import static com.weplaykit.sdk.module.person.view.widget.ChatInput.PanelState.ISEMOJIPANELSEE;
import static com.weplaykit.sdk.module.person.view.widget.ChatInput.PanelState.ISKEYBOARDSEE;
import static com.weplaykit.sdk.module.person.view.widget.ChatInput.PanelState.ISMEDIAPANELSEE;
/**
* Created by daniel.xiao on 2017/3/7.
* 聊天输入框
*/
public class ChatInput extends RelativeLayout {
private static final String TAG = "ChatInput";
private EmojiconEditText mEtEmoji;
private ImageView mIvEmoji;
private ImageView mIvChoose;
private EmojiSelectView mSelectViewEmoji;
private ViewGroup mRootView;
private LinearLayout mLlMediaPanel;
private ImageView mIvChoosePic;
private ImageView mIvTakePic;
private Context mContext;
private PanelState mState;
private TextView mBtnSend;
private PrivateMsgDetailContract.IView mView;
private final int REQUEST_CODE_ASK_PERMISSIONS = 100;
public ChatInput(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mRootView = (ViewGroup) LayoutInflater.from(context)
.inflate(MR.getIdByLayoutName(context, "wpk_common_chat_input"), this);
mState = ISALLUNSEE;
initView(context);
initListener();
}
private void initView(Context context) {
mEtEmoji = MR.getViewByIdName(context, mRootView, "emoj_et_content");
mIvEmoji = MR.getViewByIdName(context, mRootView, "iv_emoji");
mIvChoose = MR.getViewByIdName(context, mRootView, "iv_img");
mSelectViewEmoji = MR.getViewByIdName(context, mRootView, "emoji_select_view");
mLlMediaPanel = MR.getViewByIdName(context, mRootView, "ll_media_panel");
mIvChoosePic = MR.getViewByIdName(context, mRootView, "iv_choose_picture");
mIvTakePic = MR.getViewByIdName(context, mRootView, "iv_take_picture");
mBtnSend = MR.getViewByIdName(context, mRootView, "btn_send");
mSelectViewEmoji.setNeedShowEmojEdt(mEtEmoji);
}
private void initListener() {
// 控制键盘、emoji、媒体入口显示
clickPanel();
//选择相册
mIvChoosePic.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Activity activity = (Activity) getContext();
if(activity!=null && requestStorage(activity)){
ChatInput.this.mView.sendImage();
}
}
});
//选择相机
mIvTakePic.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Activity activity = (Activity) getContext();
if(activity!=null && requestCamera(activity)){
ChatInput.this.mView.sendPhoto();
}
}
});
// 发送按钮监听
mEtEmoji.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEND) {
String content = mEtEmoji.getText().toString();
if(!TextUtils.isEmpty(content)){
mEtEmoji.setText("");
ChatInput.this.mView.sendText(content);
}
return true;
}
return false;
}
});
//发送消息按钮
mBtnSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String content = mEtEmoji.getText().toString();
if(!TextUtils.isEmpty(content)){
mEtEmoji.setText("");
ChatInput.this.mView.sendText(content);
}
}
});
}
private void showOnBaseState(PanelState mState){
switch (mState){
case ISMEDIAPANELSEE:
break;
case ISEMOJIPANELSEE:
break;
case ISKEYBOARDSEE:
break;
case ISALLUNSEE:
break;
}
}
/**
* 控制键盘、emoji、媒体入口显示
*/
private void clickPanel(){
//控制键盘、emoji、媒体入口显示
mEtEmoji.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mState == ISEMOJIPANELSEE){
mSelectViewEmoji.setVisibility(View.GONE);
mLlMediaPanel.setVisibility(View.GONE);
SoftKeyboardUtil.showKeyBoard(mEtEmoji);
mState = ISKEYBOARDSEE;
}else if(mState == ISMEDIAPANELSEE){
mLlMediaPanel.setVisibility(View.GONE);
mSelectViewEmoji.setVisibility(View.GONE);
SoftKeyboardUtil.showKeyBoard(mEtEmoji);
mState = ISKEYBOARDSEE;
}
}
});
mEtEmoji.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
//SoftKeyboardUtil.showKeyBoard(mEtEmoji);
mSelectViewEmoji.setVisibility(View.GONE);
mLlMediaPanel.setVisibility(View.GONE);
mState = ISKEYBOARDSEE;
}
}
});
//控制键盘、emoji、媒体入口显示
mIvEmoji.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mState == ISEMOJIPANELSEE ){
// 隐藏emoji,显示键盘
mSelectViewEmoji.setVisibility(View.GONE); //改用动画
SoftKeyboardUtil.showKeyBoard(mEtEmoji);
mState = ISKEYBOARDSEE;
}else if(mState == ISKEYBOARDSEE || mState == ISALLUNSEE){
// 隐藏键盘,显示emoji
SoftKeyboardUtil.hideSoftKeyBoard(mEtEmoji);
WPKApplication.runOnUIThread(new Runnable() {
@Override
public void run() {
mSelectViewEmoji.setVisibility(View.VISIBLE); //改用动画
}
}, 300);
mState = ISEMOJIPANELSEE;
}else if(mState == ISMEDIAPANELSEE){
mSelectViewEmoji.setVisibility(View.VISIBLE);
mLlMediaPanel.setVisibility(View.GONE);
SoftKeyboardUtil.hideSoftKeyBoard(mEtEmoji);
mState = ISEMOJIPANELSEE;
}
}
});
//控制键盘、emoji、媒体入口显示
mIvChoose.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mState == ISALLUNSEE || mState == ISKEYBOARDSEE ){
SoftKeyboardUtil.hideSoftKeyBoard(mContext);
mState = ISMEDIAPANELSEE;
WPKApplication.runOnUIThread(new Runnable() {
@Override
public void run() {
mLlMediaPanel.setVisibility(View.VISIBLE); //改用动画
}
}, 300);
}else if(mState == ISMEDIAPANELSEE){
mLlMediaPanel.setVisibility(View.GONE);
SoftKeyboardUtil.showKeyBoard(mEtEmoji);
mState = ISKEYBOARDSEE;
}else if(mState == ISEMOJIPANELSEE){
mLlMediaPanel.setVisibility(View.VISIBLE);
SoftKeyboardUtil.hideSoftKeyBoard(mEtEmoji);
mSelectViewEmoji.setVisibility(View.GONE);
mState = ISMEDIAPANELSEE;
}
}
});
}
enum PanelState{
ISMEDIAPANELSEE,
ISEMOJIPANELSEE,
ISKEYBOARDSEE,
ISALLUNSEE;
}
private boolean requestCamera(Activity activity){
if (afterM()){
int hasPermission = activity.checkSelfPermission(Manifest.permission.CAMERA);
if (hasPermission != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.CAMERA},
REQUEST_CODE_ASK_PERMISSIONS);
return false;
}
}
return true;
}
private boolean requestStorage(Activity activity){
if (afterM()){
int hasPermission = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasPermission != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
return false;
}
}
return true;
}
private boolean afterM(){
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
public void setView(PrivateMsgDetailContract.IView view){
this.mView = view;
}
public EmojiconEditText getmEtEmoji() {
return mEtEmoji;
}
public ImageView getmIvEmoji() {
return mIvEmoji;
}
public ImageView getmIvChoose() {
return mIvChoose;
}
public EmojiSelectView getmSelectViewEmoji() {
return mSelectViewEmoji;
}
public ViewGroup getmRootView() {
return mRootView;
}
public LinearLayout getmLlMediaPanel() {
return mLlMediaPanel;
}
public ImageView getmIvChoosePic() {
return mIvChoosePic;
}
public ImageView getmIvTakePic() {
return mIvTakePic;
}
}
分析:
构造方法里有一行代码如下:
mRootView = (ViewGroup) LayoutInflater.from(context)
.inflate(MR.getIdByLayoutName(context, "wpk_common_chat_input"), this);
看到this没有,这个this就意味着把wpk_common_chat_input的所有内容添加到根布局RelativeLayout中。这样我们就可以把ChatInput这个类当做一个ViewGroup使用了。
封装就是这么简单
好处
我们可以在这个封装类中处理各个按钮的点击事件,不在Activity或者Fragment处理,这样Activity和Fragment就没那么臃肿。
结论
有时候我们界面中的元素比较多,我们可以把一部分关联比较紧密的控件封装在一个java类中,从而实现封装给我们带来的好处。