李晨晨:
本次我主要实现了上次图片选择界面中的图片预览activity。
1.首先在上次的PhotoSelectActivity中加入带result请求的页面跳转,以及相应的result处理:
- /**
- * 单击单张图片时,调整到预览页面显示该图
- */
- private void previewByItem(){
- Intent intent = new Intent(this,ImagePreviewActivity.class);
- intent.putExtra("FLAG", ImagePreviewActivity.FLAG_SHOW_ITEM);
- intent.putExtra("IMAGE_ITEM",mShowItem);
- startActivityForResult(intent,REQUEST_SHOW_ITEM);
- }
-
- /**
- * 单击“预览”按钮时,跳转到预览页面显示所有已选中的图片
- */
- private void previewByBtn(){
- Intent intent = new Intent(this,ImagePreviewActivity.class);
- intent.putExtra("FLAG", ImagePreviewActivity.FLAG_SHOW_LIST);
- intent.putExtra("IMAGE_LIST", (Serializable) mSelectedImages);
- startActivityForResult(intent,REQUEST_SHOW_LIST);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- // 预览界面点击了“发送”按钮
- if (resultCode == RESULT_OK){
- if (requestCode == REQUEST_SHOW_ITEM){
- if (mShowItem != null){
- mSelectedImages.clear();
- mSelectedImages.add(mShowItem);
- sendImage();
- }
- }else if (requestCode == REQUEST_SHOW_LIST){
- sendImage();
- }
- }
- }
2.ImagePreviewActivity中,主要分为控件id绑定,从上一个intent中获得要显示的图片,显示图片,以及自定义的PagerAdapter和IndicatorView。
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_image_preview);
- findView();
- getImageFromIntent();
- showImage();
- }
相应的布局:
activity_image_preview.xml
- <?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="match_parent"
- android:orientation="vertical">
-
- <include layout="@layout/layout_title"/>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1">
-
- <android.support.v4.view.ViewPager
- android:id="@+id/view_page"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- <com.ezreal.ezchat.photoselector.IndicatorView
- android:id="@+id/indicator_view"
- android:layout_width="match_parent"
- android:layout_height="25dp"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="5dp"
- android:gravity="center"/>
- </RelativeLayout>
-
- </LinearLayout>
item_image_pre.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/layout_img"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.bm.library.PhotoView
- android:id="@+id/iv_img"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/black"/>
-
- </RelativeLayout>
2.findView方法:其中为返回键和发送键设置了OnClickListener。
- private void findView() {
- mTvTitle = (TextView) findViewById(R.id.tv_title);
- mTvTitle.setText("预览");
-
- mIvBack = (ImageView) findViewById(R.id.iv_back);
- mIvBack.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImagePreviewActivity.this.setResult(RESULT_CANCELED);
- finish();
- }
- });
-
- mTvSend = (TextView) findViewById(R.id.tv_send);
- mTvSend.setText("发送");
- mTvSend.setTextColor(Color.WHITE);
- mTvSend.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImagePreviewActivity.this.setResult(RESULT_OK);
- finish();
- }
- });
-
- mIndicatorView = (IndicatorView) findViewById(R.id.indicator_view);
- mViewPager = (ViewPager) findViewById(R.id.view_page);
- }
3.getImageFromIntent方法:根据上一个activity不同的flag设置不同的响应。
- private void getImageFromIntent() {
- mImageBeans = new ArrayList<>();
- int flag = getIntent().getIntExtra("FLAG", FLAG_SHOW_ITEM);
- if (flag == FLAG_SHOW_ITEM) {
- ImageBean image = (ImageBean) getIntent().getSerializableExtra("IMAGE_ITEM");
- if (image != null) {
- mImageBeans.add(image);
- }
- } else if (flag == FLAG_SHOW_LIST) {
- List<ImageBean> list = (List<ImageBean>) getIntent().getSerializableExtra("IMAGE_LIST");
- if (list != null) {
- mImageBeans.addAll(list);
- }
- }
- createViews();
- }
其中用到的createViews方法:
- private void createViews() {
- mViews = new ArrayList<>();
- for (int i = 0; i < mImageBeans.size(); i++) {
- View view = LayoutInflater.from(this).inflate(R.layout.item_image_pre,
- null, false);
- PhotoView photoView = (PhotoView) view.findViewById(R.id.iv_img);
- photoView.setMaxScale(4);
- photoView.enable();
- Glide.with(ImagePreviewActivity.this)
- .load(mImageBeans.get(i).getPath()).diskCacheStrategy(DiskCacheStrategy.ALL)
- .error(R.drawable.bg_img_defalut)
- .into(photoView);
- mViews.add(view);
- }
- mIndicatorView.init(mViews.size());
- }
4.showImage方法:
- private void showImage() {
- mPageAdapter = new ViewPageAdapter(mViews);
- mViewPager.setAdapter(mPageAdapter);
- mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
-
- private int mOldPosition = 0;
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-
- }
-
- @Override
- public void onPageSelected(int position) {
- mIndicatorView.playBy(mOldPosition, position);
- mOldPosition = position;
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
-
- }
- });
- }
5.用到的自定义PagerAdapter-ViewPageAdapter
- private class ViewPageAdapter extends PagerAdapter {
-
- private List<View> mViews;
-
- public ViewPageAdapter(List<View> views) {
- mViews = views;
- }
-
- @Override
- public int getCount() {
- return mViews != null ? mViews.size() : 0;
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- container.addView(mViews.get(position));
- return mViews.get(position);
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
- container.removeView(mViews.get(position));
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
- }
6.IndicatorView选择指示器:主要是滑动图片时,相应的下面的小圆点的动画。
- public class IndicatorView extends LinearLayout {
-
- private Context mContext;
- private ArrayList<ImageView> mImageViews;
- private Bitmap mBtnSelect;
- private Bitmap mBtnNormal;
- private int mMaxHeight;
- private int mMaxWidth;
- private AnimatorSet mPlayToAnimatorSet;
- private AnimatorSet mPlayByInAnimatorSet;
- private AnimatorSet mPlayByOutAnimatorSet;
-
- public IndicatorView(Context context) {
- this(context, null);
- }
-
- public IndicatorView(Context context, AttributeSet attrs) {
- super(context, attrs);
- this.mContext = context;
- this.setOrientation(HORIZONTAL);
- mMaxWidth = mMaxHeight = dip2px(16);
- mBtnSelect = BitmapFactory.decodeResource(getResources(), R.drawable.indicator_point_select);
- mBtnNormal = BitmapFactory.decodeResource(getResources(), R.drawable.indicator_point_nomal);
- }
-
- public void init(int count) {
-
- mImageViews = new ArrayList<>();
- this.removeAllViews();
- for (int i = 0; i < count; i++) {
- RelativeLayout rl = new RelativeLayout(mContext);
- LayoutParams params = new LayoutParams(mMaxWidth, mMaxHeight);
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- ImageView imageView = new ImageView(mContext);
- if (i == 0) {
- imageView.setImageBitmap(mBtnSelect);
- rl.addView(imageView, layoutParams);
- } else {
- imageView.setImageBitmap(mBtnNormal);
- rl.addView(imageView, layoutParams);
- }
- this.addView(rl, params);
- mImageViews.add(imageView);
- }
- }
-
- public void playBy(int startPosition, int nextPosition) {
-
- boolean isShowInAnimOnly = false;
- if (startPosition < 0 || nextPosition < 0 || nextPosition == startPosition) {
- startPosition = nextPosition = 0;
- }
-
- if (startPosition < 0) {
- isShowInAnimOnly = true;
- startPosition = nextPosition = 0;
- }
-
- final ImageView imageViewStrat = mImageViews.get(startPosition);
- final ImageView imageViewNext = mImageViews.get(nextPosition);
-
- ObjectAnimator anim1 = ObjectAnimator.ofFloat(imageViewStrat,
- "scaleX", 1.0f, 0.25f);
- ObjectAnimator anim2 = ObjectAnimator.ofFloat(imageViewStrat,
- "scaleY", 1.0f, 0.25f);
-
- if (mPlayByOutAnimatorSet != null && mPlayByOutAnimatorSet.isRunning()) {
- mPlayByOutAnimatorSet.cancel();
- mPlayByOutAnimatorSet = null;
- }
- mPlayByOutAnimatorSet = new AnimatorSet();
- mPlayByOutAnimatorSet.play(anim1).with(anim2);
- mPlayByOutAnimatorSet.setDuration(100);
-
- ObjectAnimator animIn1 = ObjectAnimator.ofFloat(imageViewNext,
- "scaleX", 0.25f, 1.0f);
- ObjectAnimator animIn2 = ObjectAnimator.ofFloat(imageViewNext,
- "scaleY", 0.25f, 1.0f);
-
- if (mPlayByInAnimatorSet != null && mPlayByInAnimatorSet.isRunning()) {
- mPlayByInAnimatorSet.cancel();
- mPlayByInAnimatorSet = null;
- }
- mPlayByInAnimatorSet = new AnimatorSet();
- mPlayByInAnimatorSet.play(animIn1).with(animIn2);
- mPlayByInAnimatorSet.setDuration(100);
-
- if (isShowInAnimOnly) {
- mPlayByInAnimatorSet.start();
- return;
- }
-
- anim1.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- imageViewStrat.setImageBitmap(mBtnNormal);
- ObjectAnimator animFil1l = ObjectAnimator.ofFloat(imageViewStrat,
- "scaleX", 1.0f);
- ObjectAnimator animFill2 = ObjectAnimator.ofFloat(imageViewStrat,
- "scaleY", 1.0f);
- AnimatorSet mFillAnimatorSet = new AnimatorSet();
- mFillAnimatorSet.play(animFil1l).with(animFill2);
- mFillAnimatorSet.start();
- imageViewNext.setImageBitmap(mBtnSelect);
- mPlayByInAnimatorSet.start();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- });
- mPlayByOutAnimatorSet.start();
- }
-
- private int dip2px(float dipValue) {
- final float scale = getContext().getResources().getDisplayMetrics().density;
- return (int) (dipValue * scale + 0.5f);
- }
- }
最终效果:


下面的四个小点就是选择指示器,代表预览界面有几张图片。哪一个小点暗一点就代表显示的是那一张。
仝心:
这次的工作在上次的基础上完成录音发送功能。
自定义AudioRecordButton类继承自Button,用于实现聊天时的录音和发送语音及其他一些相关功能。
构造方法,设置按钮样式以及提示用户可以按住按钮说话
- public AudioRecordButton(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- // 初始化按钮样式
- setBackgroundResource(R.drawable.record_button_normal);
- setText(getResources().getString(R.string.press_record));//按住 说话
- }
初始化按钮,并设置长按按钮的事件监听器。
- public void init(String audioSaveDir) {
- mAudioSaveDir = audioSaveDir;
- // 初始化 dialog 管理器
- mDialogManager = new RecordDialogManager(getContext());
- // 获取音频管理,以申请音频焦点
- mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
- // 初始化录音管理器
- mAudioRecordManager = AudioRecordManager.getInstance(mAudioSaveDir);
-
- mAudioRecordManager.setAudioStateListener(this);
-
- // 设置按钮长按事件监听,只有触发长按才开始准备录音
- setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- // 获取焦点
- int focus = mAudioManager.requestAudioFocus(null,
- AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- if (focus == AudioManager.AUDIOFOCUS_REQUEST_GRANTED){
- isReady = true;
- mAudioRecordManager.prepareAudio();
- }else if (focus == AudioManager.AUDIOFOCUS_REQUEST_FAILED){
- if (mRecordingListener != null) {
- mRecordingListener.recordError("AUDIO_FOCUS_REQUEST_FAILED");
- }
- }
- return true;
- }
- });
- hasInit = true;
- }
子线程runnable,每间隔0.1秒获取音量大小,并记录录音时间
- private Runnable mGetVoiceLevelRunnable = new Runnable() {
- @Override
- public void run() {
- while (isRecording) {
- try {
- Thread.sleep(100);
- mRecordTime += 100;
- mHandler.sendEmptyMessage(MSG_VOICE_CHANGE);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- };
通过Handler关联子线程,通过Handler将Message和Runnable对象发送到该Handler所关联线程的MessageQueue(消息队列)中,然后该消息队列一直在循环拿出一个Message,对其进行处理,处理完之后拿出下一个Message,继续进行处理,周而复始。
- @SuppressLint("HandlerLeak")
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case MSG_AUDIO_PREPARED:
- // 录音管理器 prepare 成功,开始录音并显示dialog
- // 启动线程记录时间并获取音量变化
- isRecording = true;
- mDialogManager.showDialogRecord();
- // 启动线程,每隔0.1秒获取音量大小
- new Thread(mGetVoiceLevelRunnable).start();
- break;
- case MSG_VOICE_CHANGE:
- mDialogManager.updateVoiceLevel(mAudioRecordManager.getVoiceLevel(7));
- break;
- case MSG_DIALOG_DISMISS:
- mDialogManager.dismissDialog();
- break;
- }
- }
- };
改变录音提示状态,包括“按住 说话”、“松开 发送”、“松开手指 取消发送”
- private void changeState(int state) {
- if (mCurrentState != state) {
- mCurrentState = state;
- if (state == STATE_NORMAL) {
- setText(getResources().getString(R.string.press_record));
- setBackgroundResource(R.drawable.record_button_normal);
- } else if (state == STATE_RECORDING) {
- setText(getResources().getString(R.string.release_end));
- setBackgroundResource(R.drawable.record_button_recoding);
- if (isRecording) {
- mDialogManager.showRecording();
- }
- } else if (state == STATE_WANT_CANCEL) {
- setText(getResources().getString(R.string.release_cancel));
- setBackgroundResource(R.drawable.record_button_recoding);
- if (isRecording) {
- mDialogManager.showDialogWantCancel();
- }
- }
- }
- }
判断是否要取消语音发送,通过判断触控点的x、y坐标变化来判断用户行为。
- private boolean isWantToCancel(int x, int y) {
- return x < 0 || x > getWidth()
- || y < -CANCEL_HEIGHT || y > getHeight() + CANCEL_HEIGHT;
- }
释放资源,释放音频焦点
- private void reset() {
- isReady = false;
- isRecording = false;
- mRecordTime = 0;
- changeState(STATE_NORMAL);
-
- // 释放焦点
- if (mAudioManager != null){
- mAudioManager.abandonAudioFocus(null);
- }
- }
然后在上周的文本输入框中添加发送录音的功能
- // 录音按钮初始化和录音监听
- mBtnAudioRecord.init(Constant.APP_CACHE_AUDIO);
- mBtnAudioRecord.setRecordingListener(new AudioRecordButton.OnRecordingListener() {
- @Override
- public void recordFinish(String audioFilePath, long recordTime) {
- if (mLayoutListener != null) {
- mLayoutListener.audioRecordFinish(audioFilePath, recordTime);
- }
- }
-
- @Override
- public void recordError(String message) {
- if (mLayoutListener != null) {
- mLayoutListener.audioRecordError(message);
- }
- }
- });
张静:
接下来完成“验证提醒”后会跳转进入的界面以及相关功能实现
一. activity_check_notify.xml (进入验证提醒后总体界面的布局)
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
-
- <include layout="@layout/title_layout"/>
-
-
- <android.support.v7.widget.RecyclerView
- android:background="@color/interval_color"
- android:id="@+id/rcv_notify_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </LinearLayout>

二. CheckNotifyListActivity(处理验证消息)
1.初始化
(1)(2)为适配器方法
(1)设置每一项的布局
- @Override
- public int setItemLayoutId(int position) {
- return R.layout.item_check_notify;
- }
item_check_notify.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:background="@color/white_color"
- android:layout_height="wrap_content"
- android:gravity="center_vertical">
-
- <LinearLayout
- android:id="@+id/layout_notify"
- android:layout_width="match_parent"
- android:layout_height="65dp"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:paddingTop="5dp"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp">
-
- <com.joooonho.SelectableRoundedImageView
- android:padding="5dp"
- android:id="@+id/iv_head_picture"
- android:layout_width="60dp"
- android:layout_height="match_parent"
- android:scaleType="fitXY"
- app:sriv_oval="true"/>
-
- <LinearLayout
- android:id="@+id/msg_detail"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_marginLeft="5dp"
- android:layout_weight="1"
- android:gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/tv_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="1"
- android:text="@string/app_name"
- android:textColor="@color/app_black_color"/>
-
- <TextView
- android:id="@+id/tv_content"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:maxLines="1"
- android:text="@string/test_msg"
- android:textColor="@color/default_text_color"/>
- </LinearLayout>
-
-
- <TextView
- android:id="@+id/tv_do_agree"
- android:layout_marginLeft="5dp"
- android:layout_width="50dp"
- android:layout_height="30dp"
- android:gravity="center"
- android:background="@drawable/tv_btn_round_green"
- android:text="@string/do_agree"
- android:textColor="@color/app_green_color"
- android:visibility="visible"/>
-
- <TextView
- android:id="@+id/tv_do_refuse"
- android:layout_marginLeft="10dp"
- android:layout_width="50dp"
- android:layout_height="30dp"
- android:background="@drawable/tv_btn_round_red"
- android:gravity="center"
- android:text="@string/do_refuse"
- android:textColor="@color/app_red_color"
- android:visibility="visible"/>
-
- <TextView
- android:id="@+id/tv_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dp"
- android:layout_marginRight="10dp"
- android:text="@string/have_agree"
- android:visibility="gone"
- android:textColor="@color/app_black_color"/>
- </LinearLayout>
-
- <View
- android:layout_marginTop="5dp"
- android:layout_below="@+id/layout_notify"
- android:layout_width="match_parent"
- android:layout_height="0.8dp"
- android:background="@color/interval_color"/>
- </RelativeLayout>

(2)绑定控件
每一项会显示该用户头像和用户名
同时,设有两个个TextView为“同意”和“拒绝”以及一个表示信息处理状态的TextView(会显示“已拒绝”或“已同意”):
a. 若获取的系统通知的处理状态为“declined”(已拒绝),两个TextView“同意”“拒绝”均不显示,显示“已拒绝”
b. 若获取的系统通知的处理状态为“passed”(已通过验证),两个TextView“同意”“拒绝”均不显示,显示“已同意”
c.否则,同时显示“同意”,“拒绝”。(默认情况下)
为两个TextView“同意”和“拒绝”分别设置onClickListener
- @Override
- public void bindView(RViewHolder holder, final int position) {
- final AddFriendNotify item = mNotifyInfoList.get(position);
- SystemMessage message = item.getMessage();
- NimUserInfo userInfo = item.getUserInfo();
- if (userInfo != null) {
- holder.setImageByUrl(CheckNotifyListActivity.this, R.id.iv_head_picture,
- userInfo.getAvatar(), R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, userInfo.getName());
- } else {
- holder.setImageResource(R.id.iv_head_picture, R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, message.getFromAccount());
- }
-
- holder.setText(R.id.tv_content, message.getContent());
-
- TextView tv_status = holder.getTextView(R.id.tv_status);
- TextView tv_agree = holder.getTextView(R.id.tv_do_agree);
- TextView tv_refuse = holder.getTextView(R.id.tv_do_refuse);
- if (message.getStatus() == SystemMessageStatus.declined) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已拒绝");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.passed) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已同意");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.init) {
- tv_status.setText("");
- tv_status.setVisibility(View.GONE);
- tv_agree.setVisibility(View.VISIBLE);
- tv_refuse.setVisibility(View.VISIBLE);
- }
- tv_agree.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, true);
- }
- });
-
- tv_refuse.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, false);
- }
- });
- }
(3)对验证提醒界面中的某一项,若长按,可选择是否删除该条信息
- mAdapter.setItemLongClickListener(new OnItemLongClickListener() {
- @Override
- public void onItemLongClick(RViewHolder holder, int position) {
- ignoreRequest(position);
- }
- });
(4)对验证提醒界面中的某一项,若点击,可查看该用户信息
- mAdapter.setItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(RViewHolder holder, int position) {
- showAccountInfo(position);
- }
- });
(5)初始化好友添加通知监听,收到信息后刷新页面
- NimSysMsgHandler.getInstance().setMessageListener(new SystemMessageListener() {
- @Override
- public void addFriendNotify() {
- loadAddFriendNotify();
- }
- });
(6)完整初始化过程
- private void init() {
- mNotifyInfoList = new ArrayList<>();
- mAdapter = new RecycleViewAdapter<AddFriendNotify>(this, mNotifyInfoList) {
- @Override
- public int setItemLayoutId(int position) {
- return R.layout.item_check_notify;
- }
-
- @Override
- public void bindView(RViewHolder holder, final int position) {
- final AddFriendNotify item = mNotifyInfoList.get(position);
- SystemMessage message = item.getMessage();
- NimUserInfo userInfo = item.getUserInfo();
- if (userInfo != null) {
- holder.setImageByUrl(CheckNotifyListActivity.this, R.id.iv_head_picture,
- userInfo.getAvatar(), R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, userInfo.getName());
- } else {
- holder.setImageResource(R.id.iv_head_picture, R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, message.getFromAccount());
- }
-
- holder.setText(R.id.tv_content, message.getContent());
-
- TextView tv_status = holder.getTextView(R.id.tv_status);
- TextView tv_agree = holder.getTextView(R.id.tv_do_agree);
- TextView tv_refuse = holder.getTextView(R.id.tv_do_refuse);
- if (message.getStatus() == SystemMessageStatus.declined) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已拒绝");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.passed) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已同意");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.init) {
- tv_status.setText("");
- tv_status.setVisibility(View.GONE);
- tv_agree.setVisibility(View.VISIBLE);
- tv_refuse.setVisibility(View.VISIBLE);
- }
- tv_agree.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, true);
- }
- });
-
- tv_refuse.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, false);
- }
- });
- }
- };
- //若长按,可选择是否删除该条信息
- mAdapter.setItemLongClickListener(new OnItemLongClickListener() {
- @Override
- public void onItemLongClick(RViewHolder holder, int position) {
- ignoreRequest(position);
- }
- });
-
- //若点击,可查看该用户信息
- mAdapter.setItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(RViewHolder holder, int position) {
- showAccountInfo(position);
- }
- });
-
- mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- mRecyclerView.setAdapter(mAdapter);
-
- // Tool Bar
- mIvBack.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- finish();
- }
- });
-
- // 初始化好友添加通知监听,收到信息后刷新页面
- NimSysMsgHandler.getInstance().setMessageListener(new SystemMessageListener() {
- @Override
- public void addFriendNotify() {
- loadAddFriendNotify();
- }
- });
-
- loadAddFriendNotify();
- }
2. 读取好友添加通知数据(loadAddFriendNotify)
(1)获取“添加朋友”消息列表
通过NimClient的getService接口获取到SystemMessageService(系统通知消息接口)服务实例,调用querySystemMessageByTypeBlock方法根据类型查询系统通知列表
(2)根据对方账户,获取账户信息,构建显示item数据
item数据在两种情况下不显示:
a. 若获取到的系统通知的处理状态为ignored(已忽略)
b. 若获取不到该条记录的账户数据
其余显示的item设置信息,设置好友(通过NimFriendHandler的CheckIsMyFriend(检查该账户是否为我的好友)),设置信息,添加到通知列表
(3)刷新界面
(4)将“添加朋友”消息置为已读
- private void loadAddFriendNotify() {
- List<SystemMessageType> types = new ArrayList<>();
- types.add(SystemMessageType.AddFriend);
-
- // 获取“添加朋友”消息列表
- List<SystemMessage> msgList = NIMClient.getService(SystemMessageService.class)
- .querySystemMessageByTypeBlock(types, 0, LOAD_MESSAGE_COUNT);
-
- // 根据对方账户,获取账户信息,构建显示 item 数据
- AddFriendNotify notify;
- List<AddFriendNotify> notifyInfoList = new ArrayList<>();
- for (SystemMessage message : msgList) {
- // 若用户已选择忽略这条消息,则跳过不显示
- if (message.getStatus() == SystemMessageStatus.ignored) {
- continue;
- }
- NimUserInfo userInfo = NimUserHandler.getInstance().getUserInfo();
- //若获取不到该条记录的账户数据,也跳过不显示
- if (userInfo == null) {
- return;
- }
-
- notify = new AddFriendNotify();
- notify.setMessage(message);
- notify.setMyFriend(NimFriendHandler.getInstance().CheckIsMyFriend(message.getFromAccount()));
- notify.setUserInfo(userInfo);
- notifyInfoList.add(notify);
- }
-
- // 刷新界面
- mNotifyInfoList.clear();
- mNotifyInfoList.addAll(notifyInfoList);
- mAdapter.notifyDataSetChanged();
-
- // 将“添加朋友”消息至为已读
- NIMClient.getService(SystemMessageService.class)
- .resetSystemMessageUnreadCountByType(types);
- }
3. 处理好友请求(dealRequest)
通过NimClient的getService接口获取到FriendService(好友管理/好友关系/黑名单关系/消息提醒相关操作)服务实例,调用ackAddFriendRequest方法进行同意/拒绝好友请求
设置回调,三种情况
(1)成功(onSuccess)
a. 如果同意,则将系统消息状态设置为"passed"(已通过验证)
b. 否则,将系统消息状态设置为"declined"(已拒绝)
通过NimClient的getService接口获取到SystemMessageService(系统通知消息接口)服务实例调用setSystemMessageStatus
方法设置系统通知状态(根据前面同意与否所决定的状态设置)
(2)失败(onFailed):显示消息“处理失败,code:xxx”
(3)出错(onException):显示消息“处理出错:xxx”
- private void dealRequest(String account, int position, final boolean agree) {
- final SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(FriendService.class)
- .ackAddFriendRequest(account, agree).setCallback(new RequestCallback<Void>() {
- @Override
- public void onSuccess(Void param) {
- SystemMessageStatus status;
- if (agree) {
- status = SystemMessageStatus.passed;
- } else {
- status = SystemMessageStatus.declined;
- }
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(), status);
- message.setStatus(status);
- mAdapter.notifyDataSetChanged();
- haveChange = true;
- }
-
- @Override
- public void onFailed(int code) {
- ToastUtils.showMessage(CheckNotifyListActivity.this, "处理失败,code:" + code);
- }
-
- @Override
- public void onException(Throwable exception) {
- ToastUtils.showMessage(CheckNotifyListActivity.this, "处理出错:" + exception.getMessage());
- }
- });
- }
4. 删除并忽略该条记录——对应于初始化中若长按某一项所进行的操作
利用AlertDialog:
(1)setMessege:设置对话框中的内容为“是否删除该条记录?”
(2)setCancelable(true):设置当点对话框以外的地方,退出对话框
(3)setPositiveButton:确定删除,通过NimClient的getService接口获取到SystemMessageService()服务实例,调用setSystemMessageStatus方法设置状态为ignored
通知列表中删除该条
退出对话框
(4)setNegativeButton:取消,退出对话框
- private void ignoreRequest(final int position) {
- new AlertDialog.Builder(this)
- .setMessage("是否删除该条记录?")
- .setCancelable(true)
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(),
- SystemMessageStatus.ignored);
- mNotifyInfoList.remove(position);
- mAdapter.notifyDataSetChanged();
- dialog.dismiss();
- }
- })
- .setNegativeButton("取消", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- }).show();
-
- }
5. 显示账号信息(showAccountInfo)——对应于初始化中若点击,可查看该用户信息
跳转到FriendInfoActivity(之前博客已写)
a. 若已经是朋友(flag == FLAG_SHOW_FRIEND),则FriendInfoActivity中可选择“发送信息”,“视频聊天”
b. 否则(flag == FLAG_ADD_FRIEND), 则FriendInfoActivity中只可选择“添加到通讯录”
- private void showAccountInfo(int position){
- AddFriendNotify notifyInfo = mNotifyInfoList.get(position);
- Intent intent = new Intent(this,FriendInfoActivity.class);
- intent.putExtra("NimUserInfo",notifyInfo.getUserInfo());
- if (notifyInfo.isMyFriend()){
- intent.putExtra("FLAG",FriendInfoActivity.FLAG_SHOW_FRIEND);
- }else {
- intent.putExtra("FLAG",FriendInfoActivity.FLAG_ADD_FRIEND);
- }
- startActivity(intent);
- }
附上完整CheckNotifyListActivity.java
- package com.ezreal.ezchat.activity;
-
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.os.Bundle;
- import android.support.annotation.Nullable;
- import android.support.v7.app.AlertDialog;
- import android.support.v7.widget.LinearLayoutManager;
- import android.support.v7.widget.RecyclerView;
- import android.view.View;
- import android.widget.TextView;
-
- import com.ezreal.ezchat.R;
- import com.ezreal.ezchat.bean.AddFriendNotify;
- import com.ezreal.ezchat.handler.NimFriendHandler;
- import com.ezreal.ezchat.handler.NimUserHandler;
- import com.ezreal.ezchat.handler.NimSysMsgHandler;
- import com.ezreal.ezchat.handler.NimSysMsgHandler.SystemMessageListener;
- import com.netease.nimlib.sdk.NIMClient;
- import com.netease.nimlib.sdk.RequestCallback;
- import com.netease.nimlib.sdk.friend.FriendService;
- import com.netease.nimlib.sdk.msg.SystemMessageService;
- import com.netease.nimlib.sdk.msg.constant.SystemMessageStatus;
- import com.netease.nimlib.sdk.msg.constant.SystemMessageType;
- import com.netease.nimlib.sdk.msg.model.SystemMessage;
- import com.netease.nimlib.sdk.uinfo.model.NimUserInfo;
- import com.ezreal.ezchat.commonlibrary.adapter.OnItemClickListener;
- import com.ezreal.ezchat.commonlibrary.adapter.OnItemLongClickListener;
- import com.ezreal.ezchat.commonlibrary.adapter.RViewHolder;
- import com.ezreal.ezchat.commonlibrary.adapter.RecycleViewAdapter;
- import com.ezreal.ezchat.commonlibrary.utils.ToastUtils;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import butterknife.BindView;
- import butterknife.ButterKnife;
-
- /**
- * Created by 张静
- */
-
- public class CheckNotifyListActivity extends BaseActivity {
-
- public static final int RESULT_HAVE_CHANGE = 0x4000;
- private static final int LOAD_MESSAGE_COUNT = 500;
- @BindView(R.id.rcv_notify_list)
- RecyclerView mRecyclerView;
- private List<AddFriendNotify> mNotifyInfoList;
- private RecycleViewAdapter<AddFriendNotify> mAdapter;
- private boolean haveChange = false;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setStatusBarColor(R.color.app_blue_color);
- setContentView(R.layout.activity_check_notify);
- setTitleBar("验证提醒", true, true);
- ButterKnife.bind(this);
- init();
- }
-
- private void init() {
- mNotifyInfoList = new ArrayList<>();
- mAdapter = new RecycleViewAdapter<AddFriendNotify>(this, mNotifyInfoList) {
- @Override
- public int setItemLayoutId(int position) {
- return R.layout.item_check_notify;
- }
-
- @Override
- public void bindView(RViewHolder holder, final int position) {
- final AddFriendNotify item = mNotifyInfoList.get(position);
- SystemMessage message = item.getMessage();
- NimUserInfo userInfo = item.getUserInfo();
- if (userInfo != null) {
- holder.setImageByUrl(CheckNotifyListActivity.this, R.id.iv_head_picture,
- userInfo.getAvatar(), R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, userInfo.getName());
- } else {
- holder.setImageResource(R.id.iv_head_picture, R.mipmap.bg_img_defalut);
- holder.setText(R.id.tv_name, message.getFromAccount());
- }
-
- holder.setText(R.id.tv_content, message.getContent());
-
- TextView tv_status = holder.getTextView(R.id.tv_status);
- TextView tv_agree = holder.getTextView(R.id.tv_do_agree);
- TextView tv_refuse = holder.getTextView(R.id.tv_do_refuse);
- if (message.getStatus() == SystemMessageStatus.declined) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已拒绝");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.passed) {
- tv_agree.setVisibility(View.GONE);
- tv_refuse.setVisibility(View.GONE);
- tv_status.setText("已同意");
- tv_status.setVisibility(View.VISIBLE);
- } else if (message.getStatus() == SystemMessageStatus.init) {
- tv_status.setText("");
- tv_status.setVisibility(View.GONE);
- tv_agree.setVisibility(View.VISIBLE);
- tv_refuse.setVisibility(View.VISIBLE);
- }
- tv_agree.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, true);
- }
- });
-
- tv_refuse.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dealRequest(item.getMessage().getFromAccount(), position, false);
- }
- });
- }
- };
- mAdapter.setItemLongClickListener(new OnItemLongClickListener() {
- @Override
- public void onItemLongClick(RViewHolder holder, int position) {
- ignoreRequest(position);
- }
- });
-
- mAdapter.setItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(RViewHolder holder, int position) {
- showAccountInfo(position);
- }
- });
-
- mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- mRecyclerView.setAdapter(mAdapter);
-
- // Tool Bar
- mIvBack.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- finish();
- }
- });
-
- // 初始化好友添加通知监听,收到信息后刷新页面
- NimSysMsgHandler.getInstance().setMessageListener(new SystemMessageListener() {
- @Override
- public void addFriendNotify() {
- loadAddFriendNotify();
- }
- });
-
- loadAddFriendNotify();
- }
-
- /**
- * 读取好友添加通知数据
- */
- private void loadAddFriendNotify() {
- List<SystemMessageType> types = new ArrayList<>();
- types.add(SystemMessageType.AddFriend);
-
- // 获取“添加朋友”消息列表
- List<SystemMessage> msgList = NIMClient.getService(SystemMessageService.class)
- .querySystemMessageByTypeBlock(types, 0, LOAD_MESSAGE_COUNT);
-
- // 根据对方账户,获取账户信息,构建显示 item 数据
- AddFriendNotify notify;
- List<AddFriendNotify> notifyInfoList = new ArrayList<>();
- for (SystemMessage message : msgList) {
- // 若用户已选择忽略这条消息,则跳过不显示
- if (message.getStatus() == SystemMessageStatus.ignored) {
- continue;
- }
- NimUserInfo userInfo = NimUserHandler.getInstance().getUserInfo();
- //若获取不到该条记录的账户数据,也跳过不显示
- if (userInfo == null) {
- return;
- }
-
- notify = new AddFriendNotify();
- notify.setMessage(message);
- notify.setMyFriend(NimFriendHandler.getInstance().CheckIsMyFriend(message.getFromAccount()));
- notify.setUserInfo(userInfo);
- notifyInfoList.add(notify);
- }
-
- // 刷新界面
- mNotifyInfoList.clear();
- mNotifyInfoList.addAll(notifyInfoList);
- mAdapter.notifyDataSetChanged();
-
- // 将“添加朋友”消息至为已读
- NIMClient.getService(SystemMessageService.class)
- .resetSystemMessageUnreadCountByType(types);
- }
-
- /**
- * 处理好友请求
- *
- * @param account 对方账户
- * @param position 列表位置
- * @param agree 是否同意
- */
- private void dealRequest(String account, int position, final boolean agree) {
- final SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(FriendService.class)
- .ackAddFriendRequest(account, agree).setCallback(new RequestCallback<Void>() {
- @Override
- public void onSuccess(Void param) {
- SystemMessageStatus status;
- if (agree) {
- status = SystemMessageStatus.passed;
- } else {
- status = SystemMessageStatus.declined;
- }
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(), status);
- message.setStatus(status);
- mAdapter.notifyDataSetChanged();
- haveChange = true;
- }
-
- @Override
- public void onFailed(int code) {
- ToastUtils.showMessage(CheckNotifyListActivity.this, "处理失败,code:" + code);
- }
-
- @Override
- public void onException(Throwable exception) {
- ToastUtils.showMessage(CheckNotifyListActivity.this, "处理出错:" + exception.getMessage());
- }
- });
- }
-
- /**
- * 删除并忽略该条记录
- * @param position 所在位置
- */
- private void ignoreRequest(final int position) {
- new AlertDialog.Builder(this)
- .setMessage("是否删除该条记录?")
- .setCancelable(true)
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(),
- SystemMessageStatus.ignored);
- mNotifyInfoList.remove(position);
- mAdapter.notifyDataSetChanged();
- dialog.dismiss();
- new AlertDialog.Builder(this)
- .setMessage("是否删除该条记录?")
- .setCancelable(true)
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(),
- SystemMessageStatus.ignored);
- mNotifyInfoList.remove(position);
- mAdapter.notifyDataSetChanged();
- dialog.dismiss();
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SystemMessage message = mNotifyInfoList.get(position).getMessage();
- NIMClient.getService(SystemMessageService.class)
- .setSystemMessageStatus(message.getMessageId(),
- SystemMessageStatus.ignored);
- mNotifyInfoList.remove(position);
- mAdapter.notifyDataSetChanged();
- dialog.dismiss();
- }
- })
- .setNegativeButton("取消", new DialogInterface.OnClickListener() {
- SystemMessageStatus.ignored);
- &nbs