私聊改造:新增快速发送图片功能

This commit is contained in:
huangjian
2023-01-12 18:34:48 +08:00
parent 69f0d76330
commit dee4f873b4
18 changed files with 494 additions and 261 deletions

View File

@@ -20,6 +20,7 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Chronometer; import android.widget.Chronometer;
import android.widget.EditText; import android.widget.EditText;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@@ -27,7 +28,11 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.effective.android.panel.PanelSwitchHelper; import com.effective.android.panel.PanelSwitchHelper;
import com.effective.android.panel.interfaces.PanelHeightMeasurer; import com.effective.android.panel.interfaces.PanelHeightMeasurer;
import com.effective.android.panel.interfaces.listener.OnPanelChangeListener; import com.effective.android.panel.interfaces.listener.OnPanelChangeListener;
@@ -35,6 +40,8 @@ import com.effective.android.panel.view.panel.IPanelView;
import com.effective.android.panel.view.panel.PanelView; import com.effective.android.panel.view.panel.PanelView;
import com.mango.moshen.R; import com.mango.moshen.R;
import com.mango.moshen.ui.im.actions.GiftAction; import com.mango.moshen.ui.im.actions.GiftAction;
import com.mango.moshen.ui.im.adpter.PhotoPreviewAdapter;
import com.mango.xchat_android_library.utils.ListUtils;
import com.mango.xchat_android_library.utils.SingleToastUtil; import com.mango.xchat_android_library.utils.SingleToastUtil;
import com.mango.xchat_android_library.utils.SizeUtils; import com.mango.xchat_android_library.utils.SizeUtils;
import com.netease.nim.uikit.api.NimUIKit; import com.netease.nim.uikit.api.NimUIKit;
@@ -48,10 +55,14 @@ import com.netease.nim.uikit.business.session.emoji.EmoticonPickerView;
import com.netease.nim.uikit.business.session.emoji.IEmoticonSelectedListener; import com.netease.nim.uikit.business.session.emoji.IEmoticonSelectedListener;
import com.netease.nim.uikit.business.session.emoji.MoonUtil; import com.netease.nim.uikit.business.session.emoji.MoonUtil;
import com.netease.nim.uikit.business.session.event.ActiveEvent; import com.netease.nim.uikit.business.session.event.ActiveEvent;
import com.netease.nim.uikit.business.session.helper.SendImageHelper;
import com.netease.nim.uikit.business.session.module.Container; import com.netease.nim.uikit.business.session.module.Container;
import com.netease.nim.uikit.business.session.module.input.ActionsPanel; import com.netease.nim.uikit.business.session.module.input.ActionsPanel;
import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent; import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent;
import com.netease.nim.uikit.common.antispam.AntiSpamEvent; import com.netease.nim.uikit.common.antispam.AntiSpamEvent;
import com.netease.nim.uikit.common.media.picker.PickImageHelper;
import com.netease.nim.uikit.common.media.picker.model.AlbumInfo;
import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper; import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper;
import com.netease.nim.uikit.common.util.AntiSpamUtil; import com.netease.nim.uikit.common.util.AntiSpamUtil;
import com.netease.nim.uikit.common.util.log.LogUtil; import com.netease.nim.uikit.common.util.log.LogUtil;
@@ -73,8 +84,17 @@ import com.netease.nimlib.sdk.msg.model.IMMessage;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
/** /**
* 底部文本编辑,语音等模块 * 底部文本编辑,语音等模块
* Created by hzxuwen on 2015/6/16. * Created by hzxuwen on 2015/6/16.
@@ -84,11 +104,10 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
private static final String TAG = "MsgSendLayout"; private static final String TAG = "MsgSendLayout";
private static final int SHOW_LAYOUT_DELAY = 0; private static final int SHOW_LAYOUT_DELAY = 0;
private final List<PhotoInfo> selectPhotos = new ArrayList<>();
protected Container container; protected Container container;
protected View view; protected View view;
protected Handler uiHandler; protected Handler uiHandler;
protected EditText messageEditText;// 文本消息编辑框 protected EditText messageEditText;// 文本消息编辑框
protected Button audioRecordBtn; // 录音按钮 protected Button audioRecordBtn; // 录音按钮
protected View audioAnimLayout; // 录音动画布局 protected View audioAnimLayout; // 录音动画布局
@@ -96,7 +115,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
protected View switchToTextButtonInInputBar;// 文本消息选择按钮 protected View switchToTextButtonInInputBar;// 文本消息选择按钮
protected View switchToAudioButtonInInputBar;// 语音消息选择按钮 protected View switchToAudioButtonInInputBar;// 语音消息选择按钮
protected View sendMessageButtonInInputBar;// 发送消息按钮 protected View sendMessageButtonInInputBar;// 发送消息按钮
protected View emojiButtonInInputBar;// 发送消息按钮 protected ImageView emojiButtonInInputBar;// 发送消息按钮
protected View messageInputBar; protected View messageInputBar;
// 表情 // 表情
protected EmoticonPickerView emoticonPickerView; // 贴图表情控件 protected EmoticonPickerView emoticonPickerView; // 贴图表情控件
@@ -110,14 +129,13 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
private boolean started = false; private boolean started = false;
private boolean cancelled = false; private boolean cancelled = false;
private boolean touched = false; // 是否按着 private boolean touched = false; // 是否按着
private boolean isKeyboardShowed = true; // 是否显示键盘 private boolean isKeyboardShowed = false; // 是否显示键盘
private boolean isTextAudioSwitchShow; // 是否展示左侧语音按钮 private boolean isTextAudioSwitchShow; // 是否展示左侧语音按钮
// adapter // adapter
private List<BaseAction> actions; private List<BaseAction> actions;
// data // data
private long typingTime = 0; private long typingTime = 0;
private TextWatcher aitTextWatcher; private TextWatcher aitTextWatcher;
private volatile boolean disable;
private boolean isChat; private boolean isChat;
private PanelSwitchHelper mHelper; private PanelSwitchHelper mHelper;
private final Runnable showTextRunnable = new Runnable() { private final Runnable showTextRunnable = new Runnable() {
@@ -129,6 +147,12 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
private ImageView ivImage; private ImageView ivImage;
private ImageView ivCamera; private ImageView ivCamera;
private ImageView ivGift; private ImageView ivGift;
private CheckBox cbOrigin;
private TextView tvSendImage;
private RecyclerView rvPreviewPhotos;
private PhotoPreviewAdapter photoPreviewAdapter;
private int previewPhotoNum;
private TextView tvUserPhoto;
/** /**
* ************************* 键盘布局切换 ******************************* * ************************* 键盘布局切换 *******************************
*/ */
@@ -152,7 +176,6 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
mHelper.resetState(); mHelper.resetState();
} else if (v == ivGift) { } else if (v == ivGift) {
ivGift.postDelayed(() -> { ivGift.postDelayed(() -> {
for (BaseAction action : actions) { for (BaseAction action : actions) {
if (action instanceof GiftAction) { if (action instanceof GiftAction) {
@@ -162,7 +185,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
}, !mHelper.isResetState() ? 300 : 0); }, !mHelper.isResetState() ? 300 : 0);
mHelper.resetState(); mHelper.resetState();
} else if (v == ivImage) { } else if (v == tvUserPhoto) {
for (BaseAction action : actions) { for (BaseAction action : actions) {
if (action instanceof PhotoAction) { if (action instanceof PhotoAction) {
action.onClick(); action.onClick();
@@ -170,6 +193,29 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
} }
mHelper.resetState(); mHelper.resetState();
} else if (v == tvSendImage) {
if (!isChat) {
SingleToastUtil.showToast("暂未达到可发起私聊等级");
return;
}
if (photoPreviewAdapter != null) {
for (BaseAction action : actions) {
if (action instanceof PhotoAction) {
SendImageHelper.sendPhotos(container.activity, (PhotoAction) action, selectPhotos, cbOrigin.isChecked());
selectPhotos.clear();
for (PhotoInfo info : photoPreviewAdapter.getData()) {
info.setIndex(0);
info.setChoose(false);
}
previewPhotoNum = 0;
tvSendImage.setEnabled(false);
photoPreviewAdapter.notifyDataSetChanged();
break;
}
}
mHelper.resetState();
}
} }
} }
}; };
@@ -192,8 +238,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
int[] location = new int[2]; int[] location = new int[2];
view.getLocationOnScreen(location); view.getLocationOnScreen(location);
return event.getRawX() < location[0] || event.getRawX() > location[0] + view.getWidth() return event.getRawX() < location[0] || event.getRawX() > location[0] + view.getWidth() || event.getRawY() < location[1] - 40;
|| event.getRawY() < location[1] - 40;
} }
public void onPause() { public void onPause() {
@@ -211,7 +256,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
public boolean collapse(boolean immediately) { public boolean collapse(boolean immediately) {
boolean respond = !mHelper.isResetState(); boolean respond = mHelper.isPanelState() || mHelper.isKeyboardState() || isKeyboardShowed;
mHelper.resetState(); mHelper.resetState();
return respond; return respond;
} }
@@ -225,61 +270,56 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
initInputBarListener(); initInputBarListener();
initTextEdit(); initTextEdit();
initAudioRecordButton(); initAudioRecordButton();
initPanelSwitchHelper();
restoreText(false); restoreText(false);
for (int i = 0; i < actions.size(); ++i) { for (int i = 0; i < actions.size(); ++i) {
actions.get(i).setIndex(i); actions.get(i).setIndex(i);
actions.get(i).setContainer(container); actions.get(i).setContainer(container);
} }
if (disable) {
disableButtons();
} }
private void initPanelSwitchHelper() {
if (mHelper == null) { if (mHelper == null) {
mHelper = new PanelSwitchHelper.Builder(container.activity) mHelper = new PanelSwitchHelper.Builder(container.activity)
//可选
.addKeyboardStateListener((visible, height) -> {
Log.d(TAG, "系统键盘是否可见 : " + visible + " 高度为:" + height);
})
//可选
.addEditTextFocusChangeListener((view, hasFocus) -> {
Log.d(TAG, "输入框是否获得焦点 : " + hasFocus);
})
//可选
.addViewClickListener(view -> { .addViewClickListener(view -> {
if (view == null) return; if (view == null) return;
if (view.getId() == R.id.emoji_button) { if (view.getId() == R.id.emoji_button) {
switchToTextLayout(false); switchToTextLayout(false);
} }
Log.d(TAG, "点击了View : " + view);
}) })
//可选
.addPanelChangeListener(new OnPanelChangeListener() { .addPanelChangeListener(new OnPanelChangeListener() {
@Override @Override
public void onKeyboard() { public void onKeyboard() {
Log.d(TAG, "唤起系统输入法"); isKeyboardShowed = true;
container.proxy.onInputPanelExpand(); container.proxy.onInputPanelExpand();
emojiButtonInInputBar.setImageResource(R.drawable.nim_message_input_emotion_pressed);
} }
@Override @Override
public void onNone() { public void onNone() {
Log.d(TAG, "隐藏所有面板"); isKeyboardShowed = false;
emojiButtonInInputBar.setImageResource(R.drawable.nim_message_input_emotion_pressed);
} }
@Override @Override
public void onPanel(IPanelView view) { public void onPanel(IPanelView view) {
Log.d(TAG, "唤起面板 : " + view);
container.proxy.onInputPanelExpand(); container.proxy.onInputPanelExpand();
if (view.getBindingTriggerViewId() == R.id.emoji_button) {
emojiButtonInInputBar.setImageResource(R.drawable.nim_message_input_keyboard);
emoticonPickerView.show(InputPanel.this);
} else if (view.getBindingTriggerViewId() == R.id.iv_image) {
emojiButtonInInputBar.setImageResource(R.drawable.nim_message_input_emotion_pressed);
initPreviewPhotos();
}
} }
@Override @Override
public void onPanelSizeChange(IPanelView panelView, boolean portrait, int oldWidth, int oldHeight, int width, int height) { public void onPanelSizeChange(IPanelView panelView, boolean portrait, int oldWidth, int oldHeight, int width, int height) {
} }
}) }).addPanelHeightMeasurer(new PanelHeightMeasurer() {
.addPanelHeightMeasurer(new PanelHeightMeasurer() {
@Override @Override
public boolean synchronizeKeyboardHeight() { public boolean synchronizeKeyboardHeight() {
return false; return false;
@@ -294,8 +334,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
public int getPanelTriggerId() { public int getPanelTriggerId() {
return R.id.iv_image; return R.id.iv_image;
} }
}) }).addPanelHeightMeasurer(new PanelHeightMeasurer() {
.addPanelHeightMeasurer(new PanelHeightMeasurer() {
@Override @Override
public boolean synchronizeKeyboardHeight() { public boolean synchronizeKeyboardHeight() {
return false; return false;
@@ -310,8 +349,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
public int getPanelTriggerId() { public int getPanelTriggerId() {
return R.id.emoji_button; return R.id.emoji_button;
} }
}) }).logTrack(false)//output log
.logTrack(true)//output log
.build(); .build();
messageListView.setPanelSwitchHelper(mHelper); messageListView.setPanelSwitchHelper(mHelper);
@@ -319,6 +357,61 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
@SuppressLint("CheckResult")
private void initPreviewPhotos() {
if (photoPreviewAdapter != null) {
photoPreviewAdapter.notifyDataSetChanged();
return;
}
rvPreviewPhotos.setAdapter(photoPreviewAdapter = new PhotoPreviewAdapter());
rvPreviewPhotos.setItemAnimator(null);
rvPreviewPhotos.setLayoutManager(new LinearLayoutManager(container.activity, LinearLayoutManager.HORIZONTAL, false));
photoPreviewAdapter.setOnItemClickListener((adapter, view, position) -> {
PhotoInfo photoInfo = photoPreviewAdapter.getItem(position);
if (photoInfo != null) {
if (photoInfo.isChoose()) {
photoInfo.setChoose(false);
int tempIndex = photoInfo.getIndex();
for (PhotoInfo info : photoPreviewAdapter.getData()) {
if (info.getIndex() > tempIndex) {
info.setIndex(info.getIndex() - 1);
}
}
photoInfo.setIndex(0);
previewPhotoNum--;
selectPhotos.remove(tempIndex - 1);
photoPreviewAdapter.notifyDataSetChanged();
} else {
if (previewPhotoNum >= 9) {
SingleToastUtil.showToast("一次最多发送9张图片!");
return;
}
previewPhotoNum++;
photoInfo.setChoose(true);
photoInfo.setIndex(previewPhotoNum);
selectPhotos.add(photoInfo);
photoPreviewAdapter.notifyItemChanged(position);
}
tvSendImage.setEnabled(previewPhotoNum > 0);
}
});
Observable.just(PickImageHelper.getAllMediaPhotos(container.activity, 40))
.subscribeOn(Schedulers.io())
.flatMap(albumInfos -> {
List<PhotoInfo> photoInfos = new ArrayList<>();
for (AlbumInfo albumInfo : albumInfos) {
if (!ListUtils.isListEmpty(albumInfo.getList())) {
photoInfos.addAll(albumInfo.getList());
}
}
return Observable.just(photoInfos);
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoInfos -> photoPreviewAdapter.setNewData(photoInfos));
}
public void setCustomization(SessionCustomization customization) { public void setCustomization(SessionCustomization customization) {
this.customization = customization; this.customization = customization;
if (customization != null) { if (customization != null) {
@@ -331,6 +424,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
setCustomization(customization); setCustomization(customization);
} }
@SuppressLint("CheckResult")
private void initViews() { private void initViews() {
messageInputBar = view.findViewById(R.id.textMessageLayout); messageInputBar = view.findViewById(R.id.textMessageLayout);
switchToTextButtonInInputBar = view.findViewById(R.id.buttonTextMessage); switchToTextButtonInInputBar = view.findViewById(R.id.buttonTextMessage);
@@ -348,8 +442,6 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
// 表情 // 表情
emoticonPickerView = view.findViewById(R.id.emoticon_picker_view); emoticonPickerView = view.findViewById(R.id.emoticon_picker_view);
emoticonPickerView.show(this);
// 显示录音按钮 // 显示录音按钮
switchToTextButtonInInputBar.setVisibility(View.GONE); switchToTextButtonInInputBar.setVisibility(View.GONE);
switchToAudioButtonInInputBar.setVisibility(View.VISIBLE); switchToAudioButtonInInputBar.setVisibility(View.VISIBLE);
@@ -369,27 +461,13 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
ivCamera.setOnClickListener(clickListener); ivCamera.setOnClickListener(clickListener);
ivGift.setOnClickListener(clickListener); ivGift.setOnClickListener(clickListener);
} rvPreviewPhotos = view.findViewById(R.id.rv_preview_photos);
tvSendImage = view.findViewById(R.id.tv_send_image);
public void disableButtons() { tvSendImage.setEnabled(false);
if (messageEditText != null && audioRecordBtn != null && tvUserPhoto = view.findViewById(R.id.tv_user_photo);
switchToTextButtonInInputBar != null && cbOrigin = view.findViewById(R.id.cb_origin);
switchToAudioButtonInInputBar != null && tvSendImage.setOnClickListener(clickListener);
emojiButtonInInputBar != null) { tvUserPhoto.setOnClickListener(clickListener);
messageEditText.setEnabled(false);
messageEditText.setHint("禁言中,快找管理员解除禁言吧!");
messageEditText.setHintTextColor(Color.parseColor("#999999"));
audioRecordBtn.setEnabled(false);
switchToTextButtonInInputBar.setEnabled(false);
switchToAudioButtonInInputBar.setEnabled(false);
emojiButtonInInputBar.setEnabled(false);
} else {
setDisable(true);
}
}
public void setDisable(boolean disable) {
this.disable = disable;
} }
private void initInputBarListener() { private void initInputBarListener() {
@@ -405,9 +483,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
//当actionId == XX_SEND 或者 XX_DONE时都触发 //当actionId == XX_SEND 或者 XX_DONE时都触发
//或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发 //或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发
//注意这是一定要判断event != null。因为在某些输入法上会返回null。 //注意这是一定要判断event != null。因为在某些输入法上会返回null。
if (actionId == EditorInfo.IME_ACTION_SEND if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_ACTION_DONE || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction())) {
|| actionId == EditorInfo.IME_ACTION_DONE
|| (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction())) {
//处理事件 //处理事件
onTextMessageSendButtonPressed(); onTextMessageSendButtonPressed();
return true; return true;
@@ -540,7 +616,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
// 切换成音频,收起键盘,按钮切换成键盘 // 切换成音频,收起键盘,按钮切换成键盘
private void switchToAudioLayout() { private void switchToAudioLayout() {
if (!isChat) { if (!isChat) {
SingleToastUtil.showToast("等级不够"); SingleToastUtil.showToast("暂未达到可发起私聊等级");
return; return;
} }
Log.e(TAG, "switchToAudioLayout: "); Log.e(TAG, "switchToAudioLayout: ");
@@ -559,10 +635,8 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
// 隐藏键盘布局 // 隐藏键盘布局
public void hideInputMethod() { public void hideInputMethod() {
isKeyboardShowed = false;
uiHandler.removeCallbacks(showTextRunnable); uiHandler.removeCallbacks(showTextRunnable);
InputMethodManager imm = (InputMethodManager) container.activity.getSystemService(Context.INPUT_METHOD_SERVICE); mHelper.resetState();
imm.hideSoftInputFromWindow(messageEditText.getWindowToken(), 0);
messageEditText.clearFocus(); messageEditText.clearFocus();
} }
@@ -572,9 +646,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
//如果已经显示,则继续操作时不需要把光标定位到最后 //如果已经显示,则继续操作时不需要把光标定位到最后
if (!isKeyboardShowed) { if (!isKeyboardShowed) {
editTextMessage.setSelection(editTextMessage.getText().length()); editTextMessage.setSelection(editTextMessage.getText().length());
isKeyboardShowed = true;
} }
mHelper.toKeyboardState(); mHelper.toKeyboardState();
container.proxy.onInputPanelExpand(); container.proxy.onInputPanelExpand();
} }
@@ -594,7 +666,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
private void checkSendButtonEnable(EditText editText) { private void checkSendButtonEnable(EditText editText) {
String textMessage = editText.getText().toString(); String textMessage = editText.getText().toString();
setEditTextState(); setEditTextState();
if (!TextUtils.isEmpty(StringUtil.removeBlanks(textMessage)) && editText.hasFocus()) { if (!TextUtils.isEmpty(StringUtil.removeBlanks(textMessage))) {
sendMessageButtonInInputBar.setVisibility(View.VISIBLE); sendMessageButtonInInputBar.setVisibility(View.VISIBLE);
} else { } else {
sendMessageButtonInInputBar.setVisibility(View.GONE); sendMessageButtonInInputBar.setVisibility(View.GONE);
@@ -631,8 +703,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
@Override @Override
public void onTextAdd(String content, int start, int length) { public void onTextAdd(String content, int start, int length) {
if (messageEditText.getVisibility() != View.VISIBLE || if (messageEditText.getVisibility() != View.VISIBLE || (emoticonPickerView != null && emoticonPickerView.getVisibility() == View.VISIBLE)) {
(emoticonPickerView != null && emoticonPickerView.getVisibility() == View.VISIBLE)) {
switchToTextLayout(true); switchToTextLayout(true);
} else { } else {
uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY);
@@ -666,8 +737,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
touched = true; touched = true;
initAudioRecord(); initAudioRecord();
onStartAudioRecord(); onStartAudioRecord();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) {
|| event.getAction() == MotionEvent.ACTION_UP) {
touched = false; touched = false;
onEndAudioRecord(isCancelled(v, event)); onEndAudioRecord(isCancelled(v, event));
} else if (event.getAction() == MotionEvent.ACTION_MOVE) { } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
@@ -693,8 +763,7 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
* 开始语音录制 * 开始语音录制
*/ */
private void onStartAudioRecord() { private void onStartAudioRecord() {
container.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, container.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
audioMessageHelper.startRecord(); audioMessageHelper.startRecord();
cancelled = false; cancelled = false;
} }
@@ -845,15 +914,6 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
} }
} }
public void reloadActions(List<BaseAction> actions) {
this.actions = actions;
for (int i = 0; i < this.actions.size(); ++i) {
this.actions.get(i).setIndex(i);
this.actions.get(i).setContainer(container);
}
ActionsPanel.init(view, actions);
}
public void setLimitLevel(boolean isChat, String msg) { public void setLimitLevel(boolean isChat, String msg) {
this.isChat = isChat; this.isChat = isChat;
setEditTextState(); setEditTextState();
@@ -866,12 +926,22 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
messageEditText.setFocusableInTouchMode(false); messageEditText.setFocusableInTouchMode(false);
messageEditText.setEnabled(false); messageEditText.setEnabled(false);
sendMessageButtonInInputBar.setEnabled(false); sendMessageButtonInInputBar.setEnabled(false);
emojiButtonInInputBar.setEnabled(false);
switchToAudioButtonInInputBar.setEnabled(false);
ivImage.setEnabled(false);
ivCamera.setEnabled(false);
ivGift.setEnabled(false);
} else { } else {
messageEditText.setHint("请输入消息"); messageEditText.setHint("请输入消息");
messageEditText.setFocusable(true); messageEditText.setFocusable(true);
messageEditText.setFocusableInTouchMode(true); messageEditText.setFocusableInTouchMode(true);
messageEditText.setEnabled(true); messageEditText.setEnabled(true);
sendMessageButtonInInputBar.setEnabled(true); sendMessageButtonInInputBar.setEnabled(true);
emojiButtonInInputBar.setEnabled(true);
switchToAudioButtonInInputBar.setEnabled(true);
ivImage.setEnabled(true);
ivCamera.setEnabled(true);
ivGift.setEnabled(true);
} }
} }

View File

@@ -0,0 +1,29 @@
package com.mango.moshen.ui.im.adpter
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.signature.ObjectKey
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.mango.core.utils.LogUtils
import com.mango.moshen.R
import com.mango.moshen.ui.utils.ImageLoadUtilsV2
import com.netease.nim.uikit.common.media.picker.model.PhotoInfo
import com.netease.nim.uikit.support.glide.GlideApp
class PhotoPreviewAdapter :
BaseQuickAdapter<PhotoInfo, BaseViewHolder>(R.layout.item_message_photo) {
override fun convert(helper: BaseViewHolder, item: PhotoInfo) {
val imageView = helper.getView<ImageView>(R.id.iv_item_photo)
GlideApp.with(imageView)
.load(item.filePath)
.placeholder(R.drawable.default_cover)
.signature(ObjectKey(item))
.into(imageView)
val textView = helper.getView<TextView>(R.id.tv_item_number)
textView.isSelected = item.isChoose
textView.text = if (item.isChoose) "${item.index}" else ""
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="oval">
<solid android:color="#5FCCE4" />
<stroke android:width="1dp" android:color="@color/white" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/black_transparent_30" />
<stroke android:width="1dp" android:color="@color/white" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="95dp"
android:layout_height="138dp"
android:layout_marginStart="5dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="8dp">
<com.mango.moshen.common.widget.RectRoundImageView
android:id="@+id/iv_item_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:borderRadius="4dp"
app:type="round" />
<TextView
android:id="@+id/tv_item_number"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_gravity="top|end"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:background="@drawable/shape_circle_photo_preview_bg"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/white"
android:textSize="@dimen/sp_10"
tools:text="1" />
</FrameLayout>

View File

@@ -1,21 +1,60 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical">
android:layout_gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_preview_photos"
android:layout_width="match_parent"
android:layout_height="154dp"
android:background="@color/color_f4f4fa" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="16dp">
<TextView <TextView
android:id="@+id/nim_message_item_text_body" android:id="@+id/tv_user_photo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="phone|email|web" android:layout_marginStart="16dp"
android:gravity="center_vertical|left" android:text="相册"
android:includeFontPadding="false" android:textColor="@color/color_1A1A1A"
android:lineSpacingExtra="3dip" android:textSize="14sp" />
android:maxWidth="222dp"
android:text="这是选择图片的玩意" <CheckBox
android:textColor="@color/text_title_white" android:id="@+id/cb_origin"
android:textSize="@dimen/dp_13" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:button="@null"
android:drawableStart="@drawable/selector_check_box_collect"
android:drawablePadding="3dp"
android:text="原图"
android:textColor="@color/color_1A1A1A"
android:textSize="14sp" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/tv_send_image"
android:layout_width="56dp"
android:layout_height="22dp"
android:layout_marginEnd="16dp"
android:background="@drawable/common_btn_bg"
android:gravity="center"
android:text="发送"
android:textColor="@color/white"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -107,7 +107,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="30dp" android:layout_height="32dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@@ -120,19 +120,19 @@
<ImageView <ImageView
android:id="@+id/buttonAudioMessage" android:id="@+id/buttonAudioMessage"
android:layout_width="30dp" android:layout_width="32dp"
android:layout_height="30dp" android:layout_height="32dp"
android:background="@drawable/nim_message_button_bottom_audio_selector"
android:contentDescription="@string/empty" android:contentDescription="@string/empty"
android:scaleType="center" /> android:scaleType="fitXY"
android:src="@drawable/nim_message_input_voice_pressed" />
<ImageView <ImageView
android:id="@+id/buttonTextMessage" android:id="@+id/buttonTextMessage"
android:layout_width="30dp" android:layout_width="32dp"
android:layout_height="30dp" android:layout_height="32dp"
android:background="@drawable/nim_message_button_bottom_text_selector"
android:contentDescription="@string/empty" android:contentDescription="@string/empty"
android:scaleType="center" android:scaleType="fitXY"
android:src="@drawable/nim_message_input_keyboard"
android:visibility="gone" /> android:visibility="gone" />
</FrameLayout> </FrameLayout>
@@ -140,7 +140,7 @@
<Button <Button
android:id="@+id/audioRecord" android:id="@+id/audioRecord"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="30dp" android:layout_height="32dp"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginEnd="@dimen/bottom_component_margin_horizontal" android:layout_marginEnd="@dimen/bottom_component_margin_horizontal"
android:layout_weight="1" android:layout_weight="1"
@@ -153,11 +153,12 @@
<EditText <EditText
android:id="@+id/editTextMessage" android:id="@+id/editTextMessage"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="30dp" android:layout_height="32dp"
android:layout_marginEnd="@dimen/bottom_component_margin_horizontal" android:layout_marginEnd="@dimen/bottom_component_margin_horizontal"
android:layout_weight="1" android:layout_weight="1"
android:autoLink="web|email|phone" android:autoLink="web|email|phone"
android:background="@drawable/bg_message_input" android:background="@drawable/bg_message_input"
android:gravity="center_vertical"
android:hint="@string/message_hint" android:hint="@string/message_hint"
android:imeOptions="actionSend" android:imeOptions="actionSend"
android:inputType="text" android:inputType="text"
@@ -172,12 +173,12 @@
<ImageView <ImageView
android:id="@+id/emoji_button" android:id="@+id/emoji_button"
android:layout_width="30dp" android:layout_width="32dp"
android:layout_height="30dp" android:layout_height="32dp"
android:layout_marginEnd="@dimen/bottom_component_margin_horizontal" android:layout_marginEnd="@dimen/bottom_component_margin_horizontal"
android:background="@drawable/nim_message_button_bottom_emoji_selector"
android:contentDescription="@string/empty" android:contentDescription="@string/empty"
android:scaleType="center" /> android:scaleType="fitXY"
android:src="@drawable/nim_message_input_emotion_pressed" />
<TextView <TextView
android:id="@+id/buttonSendMessage" android:id="@+id/buttonSendMessage"
@@ -187,6 +188,7 @@
android:background="@drawable/common_btn_bg" android:background="@drawable/common_btn_bg"
android:contentDescription="@string/empty" android:contentDescription="@string/empty"
android:gravity="center" android:gravity="center"
android:enabled="false"
android:text="@string/send" android:text="@string/send"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="@dimen/sp_12" android:textSize="@dimen/sp_12"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -3,6 +3,6 @@
<item android:drawable="@drawable/nim_message_input_emotion_pressed" android:state_pressed="true"/> <item android:drawable="@drawable/nim_message_input_emotion_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/nim_message_input_emotion_pressed" android:state_focused="true"/> <item android:drawable="@drawable/nim_message_input_emotion_pressed" android:state_focused="true"/>
<item android:drawable="@drawable/nim_message_input_emotion"/> <item android:drawable="@drawable/nim_message_input_emotion_pressed"/>
</selector> </selector>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_grey_eaeaea" /> <solid android:color="@color/color_grey_eaeaea" />
<corners android:topLeftRadius="15dp" <corners android:topLeftRadius="8dp"
android:topRightRadius="15dp" android:topRightRadius="8dp"
android:bottomRightRadius="15dp" android:bottomRightRadius="8dp"
android:bottomLeftRadius="15dp"/> android:bottomLeftRadius="8dp"/>
</shape> </shape>

View File

@@ -28,7 +28,7 @@ public class PhotoAction extends PickImageAction {
} }
@Override @Override
protected void onPicked(File file) { public void onPicked(File file) {
IMMessage message; IMMessage message;
if (getContainer() != null && getContainer().sessionType == SessionTypeEnum.ChatRoom) { if (getContainer() != null && getContainer().sessionType == SessionTypeEnum.ChatRoom) {
message = ChatRoomMessageBuilder.createChatRoomImageMessage(getAccount(), file, file.getName()); message = ChatRoomMessageBuilder.createChatRoomImageMessage(getAccount(), file, file.getName());

View File

@@ -54,7 +54,6 @@ public class EmoticonPickerView extends LinearLayout implements IEmoticonCategor
} }
}; };
private int categoryIndex; private int categoryIndex;
private Handler uiHandler;
public EmoticonPickerView(Context context) { public EmoticonPickerView(Context context) {
super(context); super(context);
@@ -75,7 +74,6 @@ public class EmoticonPickerView extends LinearLayout implements IEmoticonCategor
private void init(Context context) { private void init(Context context) {
this.context = context; this.context = context;
this.uiHandler = new Handler(context.getMainLooper());
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.nim_emoji_layout, this); inflater.inflate(R.layout.nim_emoji_layout, this);
} }
@@ -222,7 +220,7 @@ public class EmoticonPickerView extends LinearLayout implements IEmoticonCategor
@Override @Override
public void run() { public void run() {
if (scrollView.getChildAt(0).getWidth() == 0) { if (scrollView.getChildAt(0).getWidth() == 0) {
uiHandler.postDelayed(this, 100); scrollView.postDelayed(this, 100);
} }
int x = -1; int x = -1;
View child = tabView.getChildAt(index); View child = tabView.getChildAt(index);
@@ -236,7 +234,7 @@ public class EmoticonPickerView extends LinearLayout implements IEmoticonCategor
} }
} }
}; };
uiHandler.postDelayed(runnable, 100); scrollView.postDelayed(runnable, 100);
} }

View File

@@ -8,6 +8,7 @@ import android.text.TextUtils;
import android.widget.Toast; import android.widget.Toast;
import com.netease.nim.uikit.R; import com.netease.nim.uikit.R;
import com.netease.nim.uikit.business.session.actions.PhotoAction;
import com.netease.nim.uikit.business.session.constant.Extras; import com.netease.nim.uikit.business.session.constant.Extras;
import com.netease.nim.uikit.common.media.picker.model.PhotoInfo; import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
import com.netease.nim.uikit.common.media.picker.model.PickerContract; import com.netease.nim.uikit.common.media.picker.model.PickerContract;
@@ -24,10 +25,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SendImageHelper { public class SendImageHelper {
public interface Callback {
void sendImage(File file, boolean isOrig);
}
public static void sendImageAfterPreviewPhotoActivityResult(Intent data, Callback callback) { public static void sendImageAfterPreviewPhotoActivityResult(Intent data, Callback callback) {
final ArrayList<String> selectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_SCALED_IMAGE_LIST); final ArrayList<String> selectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_SCALED_IMAGE_LIST);
final ArrayList<String> origSelectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_ORIG_IMAGE_LIST); final ArrayList<String> origSelectedImageFileList = data.getStringArrayListExtra(Extras.EXTRA_ORIG_IMAGE_LIST);
@@ -88,6 +85,16 @@ public class SendImageHelper {
} }
} }
public static void sendPhotos(Context context, PhotoAction action, List<PhotoInfo> photos, boolean isOrig) {
for (PhotoInfo photoInfo : photos) {
new SendImageTask(context, isOrig, photoInfo, (file, isOrig1) -> action.onPicked(file)).execute();
}
}
public interface Callback {
void sendImage(File file, boolean isOrig);
}
// 从相册选择图片进行发送(Added by NYB) // 从相册选择图片进行发送(Added by NYB)
public static class SendImageTask extends AsyncTask<Void, Void, File> { public static class SendImageTask extends AsyncTask<Void, Void, File> {

View File

@@ -128,4 +128,12 @@ public abstract class MsgViewHolderThumbBase extends MsgViewHolderBase {
} }
protected abstract String thumbFromSourceFile(String path); protected abstract String thumbFromSourceFile(String path);
protected int leftBackground() {
return 0;
}
protected int rightBackground() {
return 0;
}
} }

View File

@@ -2,10 +2,18 @@ package com.netease.nim.uikit.common.media.picker;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import com.netease.nim.uikit.R; import com.netease.nim.uikit.R;
import com.netease.nim.uikit.business.session.module.input.NimImageActionEvent; import com.netease.nim.uikit.business.session.module.input.NimImageActionEvent;
import com.netease.nim.uikit.common.media.dao.MediaDAO;
import com.netease.nim.uikit.common.media.picker.activity.PickImageActivity; import com.netease.nim.uikit.common.media.picker.activity.PickImageActivity;
import com.netease.nim.uikit.common.media.picker.model.AlbumInfo;
import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
import com.netease.nim.uikit.common.media.picker.util.ThumbnailsUtil;
import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog; import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog;
import com.netease.nim.uikit.common.util.storage.StorageType; import com.netease.nim.uikit.common.util.storage.StorageType;
import com.netease.nim.uikit.common.util.storage.StorageUtil; import com.netease.nim.uikit.common.util.storage.StorageUtil;
@@ -13,11 +21,18 @@ import com.netease.nim.uikit.common.util.string.StringUtil;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/** /**
* Created by huangjun on 2015/9/22. * Created by huangjun on 2015/9/22.
*/ */
public class PickImageHelper { public class PickImageHelper {
public static final String FILE_PREFIX = "file://";
/** /**
* 打开图片选择器 * 打开图片选择器
*/ */
@@ -72,6 +87,112 @@ public class PickImageHelper {
EventBus.getDefault().post(event); EventBus.getDefault().post(event);
} }
public static ArrayList<AlbumInfo> getAllMediaPhotos(Context context, int limit) {
getAllMediaThumbnails(context);
ArrayList<AlbumInfo> albumInfolist = new ArrayList<>();
int num = 0;
Cursor cursorPhotos = null;
try {
cursorPhotos = MediaDAO.getAllMediaPhotos(context);
HashMap<String, AlbumInfo> hash = new HashMap<>();
AlbumInfo albumInfo;
PhotoInfo photoInfo;
if (cursorPhotos != null && cursorPhotos.moveToFirst()) {
do {
int index = 0;
int _id = cursorPhotos.getInt(cursorPhotos.getColumnIndex(MediaStore.Images.Media._ID));
String path = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.DATA));
String album = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
long size = cursorPhotos.getLong(cursorPhotos.getColumnIndex(MediaStore.Images.Media.SIZE));
if (!isValidImageFile(path)) {
Log.d("PICKER", "it is not a vaild path:" + path);
continue;
}
num++;
List<PhotoInfo> photoList = new ArrayList<>();
photoInfo = new PhotoInfo();
if (hash.containsKey(album)) {
albumInfo = hash.remove(album);
if (albumInfolist.contains(albumInfo))
index = albumInfolist.indexOf(albumInfo);
photoInfo.setImageId(_id);
photoInfo.setFilePath(FILE_PREFIX + path);
photoInfo.setAbsolutePath(path);
photoInfo.setSize(size);
albumInfo.getList().add(photoInfo);
albumInfolist.set(index, albumInfo);
hash.put(album, albumInfo);
} else {
albumInfo = new AlbumInfo();
photoList.clear();
photoInfo.setImageId(_id);
photoInfo.setFilePath(FILE_PREFIX + path);
photoInfo.setAbsolutePath(path);
photoInfo.setSize(size);
photoList.add(photoInfo);
albumInfo.setImageId(_id);
albumInfo.setFilePath(FILE_PREFIX + path);
albumInfo.setAbsolutePath(path);
albumInfo.setAlbumName(album);
albumInfo.setList(photoList);
albumInfolist.add(albumInfo);
hash.put(album, albumInfo);
}
} while (cursorPhotos.moveToNext() && num < limit);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cursorPhotos != null) {
cursorPhotos.close();
}
} catch (Exception e) {
}
}
return albumInfolist;
}
private static void getAllMediaThumbnails(Context context) {
ThumbnailsUtil.clear();
Cursor cursorThumb = null;
try {
cursorThumb = MediaDAO.getAllMediaThumbnails(context);
if (cursorThumb != null && cursorThumb.moveToFirst()) {
int imageID;
String imagePath;
do {
imageID = cursorThumb.getInt(cursorThumb.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID));
imagePath = cursorThumb.getString(cursorThumb.getColumnIndex(MediaStore.Images.Thumbnails.DATA));
ThumbnailsUtil.put(imageID, FILE_PREFIX + imagePath);
} while (cursorThumb.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cursorThumb != null) {
cursorThumb.close();
}
} catch (Exception e) {
}
}
}
private static boolean isValidImageFile(String filePath) {
if (TextUtils.isEmpty(filePath)) {
return false;
}
File imageFile = new File(filePath);
return imageFile.exists();
}
public static class PickImageOption { public static class PickImageOption {
/** /**
* 图片选择器标题 * 图片选择器标题

View File

@@ -1,13 +1,8 @@
package com.netease.nim.uikit.common.media.picker.fragment; package com.netease.nim.uikit.common.media.picker.fragment;
import android.app.Activity; import android.app.Activity;
import android.database.Cursor;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Thumbnails;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -19,33 +14,21 @@ import android.widget.TextView;
import com.netease.nim.uikit.R; import com.netease.nim.uikit.R;
import com.netease.nim.uikit.common.fragment.TFragment; import com.netease.nim.uikit.common.fragment.TFragment;
import com.netease.nim.uikit.common.media.dao.MediaDAO; import com.netease.nim.uikit.common.media.picker.PickImageHelper;
import com.netease.nim.uikit.common.media.picker.adapter.PickerAlbumAdapter; import com.netease.nim.uikit.common.media.picker.adapter.PickerAlbumAdapter;
import com.netease.nim.uikit.common.media.picker.model.AlbumInfo; import com.netease.nim.uikit.common.media.picker.model.AlbumInfo;
import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
import com.netease.nim.uikit.common.media.picker.util.ThumbnailsUtil;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
public class PickerAlbumFragment extends TFragment implements OnItemClickListener { public class PickerAlbumFragment extends TFragment implements OnItemClickListener {
public interface OnAlbumItemClickListener {
public void OnAlbumItemClick(AlbumInfo info);
}
private OnAlbumItemClickListener onAlbumItemClickListener; private OnAlbumItemClickListener onAlbumItemClickListener;
private LinearLayout loadingLay; private LinearLayout loadingLay;
private TextView loadingTips; private TextView loadingTips;
private TextView loadingEmpty; private TextView loadingEmpty;
private ListView albumListView; private ListView albumListView;
private List<AlbumInfo> albumInfolist = new ArrayList<>();
public static final String FILE_PREFIX = "file://";
private List<AlbumInfo> albumInfolist = new ArrayList<AlbumInfo>();
private PickerAlbumAdapter albumAdapter; private PickerAlbumAdapter albumAdapter;
public PickerAlbumFragment() { public PickerAlbumFragment() {
@@ -90,13 +73,31 @@ public class PickerAlbumFragment extends TFragment implements OnItemClickListene
new ImageScanAsyncTask().execute(); new ImageScanAsyncTask().execute();
} }
private void getAllMediaPhotos() {
if (albumInfolist == null) {
albumInfolist = new ArrayList<>();
} else {
albumInfolist.clear();
}
albumInfolist.addAll(PickImageHelper.getAllMediaPhotos(getActivity(),Integer.MAX_VALUE));
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
onAlbumItemClickListener.OnAlbumItemClick(albumInfolist.get(position));
}
public interface OnAlbumItemClickListener {
void OnAlbumItemClick(AlbumInfo info);
}
private class ImageScanAsyncTask extends AsyncTask<Void, Void, Object> { private class ImageScanAsyncTask extends AsyncTask<Void, Void, Object> {
@Override @Override
protected Object doInBackground(Void... params) { protected Object doInBackground(Void... params) {
getAllMediaThumbnails();
getAllMediaPhotos(); getAllMediaPhotos();
return null; return null;
} }
@@ -117,118 +118,4 @@ public class PickerAlbumFragment extends TFragment implements OnItemClickListene
} }
} }
} }
private void getAllMediaThumbnails() {
ThumbnailsUtil.clear();
Cursor cursorThumb = null;
try {
cursorThumb = MediaDAO.getAllMediaThumbnails(getActivity());
if (cursorThumb != null && cursorThumb.moveToFirst()) {
int imageID;
String imagePath;
do {
imageID = cursorThumb.getInt(cursorThumb.getColumnIndex(Thumbnails.IMAGE_ID));
imagePath = cursorThumb.getString(cursorThumb.getColumnIndex(Thumbnails.DATA));
ThumbnailsUtil.put(imageID, FILE_PREFIX + imagePath);
} while (cursorThumb.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cursorThumb != null) {
cursorThumb.close();
}
} catch (Exception e) {
}
}
}
private void getAllMediaPhotos() {
if (albumInfolist == null) {
albumInfolist = new ArrayList<AlbumInfo>();
} else {
albumInfolist.clear();
}
Cursor cursorPhotos = null;
try {
cursorPhotos = MediaDAO.getAllMediaPhotos(getActivity());
HashMap<String, AlbumInfo> hash = new HashMap<String, AlbumInfo>();
AlbumInfo albumInfo = null;
PhotoInfo photoInfo = null;
if (cursorPhotos != null && cursorPhotos.moveToFirst()) {
do {
int index = 0;
int _id = cursorPhotos.getInt(cursorPhotos.getColumnIndex(MediaStore.Images.Media._ID));
String path = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.DATA));
String album = cursorPhotos.getString(cursorPhotos.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
long size = cursorPhotos.getLong(cursorPhotos.getColumnIndex(MediaStore.Images.Media.SIZE));
if (!isValidImageFile(path)) {
Log.d("PICKER", "it is not a vaild path:" + path);
continue;
}
List<PhotoInfo> photoList = new ArrayList<PhotoInfo>();
photoInfo = new PhotoInfo();
if (hash.containsKey(album)) {
albumInfo = hash.remove(album);
if (albumInfolist.contains(albumInfo))
index = albumInfolist.indexOf(albumInfo);
photoInfo.setImageId(_id);
photoInfo.setFilePath(FILE_PREFIX + path);
photoInfo.setAbsolutePath(path);
photoInfo.setSize(size);
albumInfo.getList().add(photoInfo);
albumInfolist.set(index, albumInfo);
hash.put(album, albumInfo);
} else {
albumInfo = new AlbumInfo();
photoList.clear();
photoInfo.setImageId(_id);
photoInfo.setFilePath(FILE_PREFIX + path);
photoInfo.setAbsolutePath(path);
photoInfo.setSize(size);
photoList.add(photoInfo);
albumInfo.setImageId(_id);
albumInfo.setFilePath(FILE_PREFIX + path);
albumInfo.setAbsolutePath(path);
albumInfo.setAlbumName(album);
albumInfo.setList(photoList);
albumInfolist.add(albumInfo);
hash.put(album, albumInfo);
}
} while (cursorPhotos.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cursorPhotos != null) {
cursorPhotos.close();
}
} catch (Exception e) {
}
}
}
private boolean isValidImageFile(String filePath) {
if (TextUtils.isEmpty(filePath)) {
return false;
}
File imageFile = new File(filePath);
if (imageFile.exists()) {
return true;
}
return false;
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
onAlbumItemClickListener.OnAlbumItemClick(albumInfolist.get(position));
}
} }

View File

@@ -11,6 +11,7 @@ public class PhotoInfo implements Serializable {
private String absolutePath; private String absolutePath;
private long size; private long size;
private boolean choose = false; private boolean choose = false;
private int index;
public int getImageId() { public int getImageId() {
return imageId; return imageId;
@@ -51,4 +52,24 @@ public class PhotoInfo implements Serializable {
public void setSize(long size) { public void setSize(long size) {
this.size = size; this.size = size;
} }
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public String toString() {
return "PhotoInfo{" +
"imageId=" + imageId +
", filePath='" + filePath + '\'' +
", absolutePath='" + absolutePath + '\'' +
", size=" + size +
", choose=" + choose +
", index=" + index +
'}';
}
} }