導語
有時候,我們項目中的需求如下圖
聊天選擇面板_PxCook.png
整個界面我們可以就理解為兩個部分,上面部分是一個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類中,從而實現封裝給我們帶來的好處。