实训第五周(1)

李晨晨:

本次主要将上周实现的图片加载方面的功能整合到photoSelectActivity。效果如下图所示:

左图为图片显示及选择界面,分为3列;右图为不同图片文件夹的选择。

     

主要内容如下

[java] view plain copy
  1. @Override  
  2.     protected void onCreate(@Nullable Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         setContentView(R.layout.activity_photo_selector);  
  5.         getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);//弹出一个窗口,让背后的窗口变暗一点  
  6.         initView();  
  7.         initImageList();  
  8.         initPopupWindow();  
  9.         loadImageData();  
  10.     }  

1.initView主要绑定view id及设置OnClickListenere;

[java] view plain copy
  1. private void initView() {  
  2.         mImageListView = (RecyclerView) findViewById(R.id.recycler_view);  
  3.         mBtnSource = (RadioButton) findViewById(R.id.btn_source_img);  
  4.         mTvFolderName = (TextView) findViewById(R.id.tv_folder_name);  
  5.         mTvPreview = (TextView) findViewById(R.id.tv_preview);  
  6.         mIvBack = (ImageView) findViewById(R.id.iv_back);  
  7.         mTvSend = (TextView) findViewById(R.id.tv_send);  
  8.   
  9.         mLayoutBottom = (RelativeLayout) findViewById(R.id.layout_bottom);  
  10.   
  11.         mIvBack.setOnClickListener(this);  
  12.         mTvSend.setOnClickListener(this);  
  13.         mTvFolderName.setOnClickListener(this);  
  14.         mTvPreview.setOnClickListener(this);  
  15.         mBtnSource.setOnClickListener(this);  
  16.   
  17.         // 文件选择按钮,只有在加载数据完成并且数据不为空的时候才可以点击  
  18.         mTvFolderName.setClickable(false);  
  19.         // 发送和预览按钮只有在有照片选择的情况下才可以点击  
  20.         mTvPreview.setClickable(false);  
  21.         mTvSend.setClickable(false);  
  22.     }  

2.initImageList主要用于初始化照片选择列表,使用recycle view显示

[java] view plain copy
  1. private void initImageList() {  
  2.         mImageBeans = new ArrayList<>();  
  3.         mImageListView.setLayoutManager(new GridLayoutManager(this3));  
  4.         mImageListView.addItemDecoration(new GridItemDecoration(this));  
  5.         mImageAdapter = new RecycleViewAdapter<ImageBean>(this, mImageBeans) {  
  6.             @Override  
  7.             public int setItemLayoutId(int position) {  
  8.                 return R.layout.item_image_sel;  
  9.             }  
  10.   
  11.             @Override  
  12.             public void bindView(RViewHolder holder, final int position) {  
  13.                 // 使用Glide加载照片,它有缓存策略,避免 OOM  
  14.                 final ImageBean item = mImageBeans.get(position);  
  15.                 ImageView imageView = holder.getImageView(R.id.iv_img);//有就拿到,没有就先加入RViewHolder的mViews列表再返回  
  16.                 Glide.with(PhotoSelectActivity.this)  
  17.                         .load(item.getPath()).diskCacheStrategy(DiskCacheStrategy.ALL)  
  18.                         .error(R.drawable.bg_img_defalut)  
  19.                         .into(imageView);  
  20.   
  21.                 // 单击照片本身,在预览窗口打开该照片  
  22.                 imageView.setOnClickListener(new View.OnClickListener() {  
  23.                     @Override  
  24.                     public void onClick(View v) {  
  25.                         mShowItem = item;  
  26.                         previewByItem();  
  27.                     }  
  28.                 });  
  29.   
  30.                 // 照片右上角的选择器,根据照片被选择与否显示不同状态 icon  
  31.                 final RadioButton radioButton = (RadioButton) holder.getConvertView()  
  32.                         .findViewById(R.id.img_sel_status);  
  33.                 radioButton.setChecked(item.isSelected());  
  34.   
  35.                 // 选择框单击事件监听,用于更新照片选择状态  
  36.                 radioButton.setOnClickListener(new View.OnClickListener() {  
  37.                     @Override  
  38.                     public void onClick(View v) {  
  39.                         ImageBean imageBean = mImageBeans.get(position);  
  40.                         if (imageBean.isSelected()) {  
  41.                             radioButton.setChecked(false);  
  42.                             imageBean.setSelected(false);  
  43.                             mSelectedImages.remove(imageBean);  
  44.                             updateBtnState();  
  45.                         } else if (mSelectedImages.size() < 9) {  
  46.                             radioButton.setChecked(true);  
  47.                             imageBean.setSelected(true);  
  48.                             mSelectedImages.add(imageBean);  
  49.                             updateBtnState();  
  50.                         } else {  
  51.                             radioButton.setChecked(false);  
  52.                             Toast.makeText(PhotoSelectActivity.this,  
  53.                                     "一次只能选择9张喔~",Toast.LENGTH_SHORT).show();  
  54.                         }  
  55.                     }  
  56.                 });  
  57.             }  
  58.         };  
  59.         mImageListView.setAdapter(mImageAdapter);  
  60.     }  

选择框状态改变需相应的改变“预览”和“发送”按钮的显示文字和可点击状态:

[java] view plain copy
  1. private void updateBtnState() {  
  2.         String size = String.valueOf(mSelectedImages.size());  
  3.         String tvSend = "发送(" + size + "/9)";  
  4.         String tvPre = "预览(" + size + "/9)";  
  5.         mTvSend.setText(tvSend);  
  6.         mTvPreview.setText(tvPre);  
  7.   
  8.         if (mSelectedImages.isEmpty()) {  
  9.             mTvSend.setClickable(false);  
  10.             mTvSend.setTextColor(getResources().getColor(R.color.blue_gray));  
  11.   
  12.             mTvPreview.setClickable(false);  
  13.             mTvPreview.setTextColor(getResources().getColor(R.color.blue_gray));  
  14.         } else {  
  15.             mTvSend.setClickable(true);  
  16.             mTvSend.setTextColor(getResources().getColor(R.color.colorAccent));  
  17.   
  18.             mTvPreview.setClickable(true);  
  19.             mTvPreview.setTextColor(getResources().getColor(R.color.colorAccent));  
  20.         }  
  21.     }  

3.initPopupWindow主要用于初始化图片文件夹选择器

[java] view plain copy
  1. private void initPopupWindow() {  
  2.        // 弹窗初始化,高度设置为屏幕的 3/4  
  3.        View rootView = LayoutInflater.from(this).inflate(R.layout.popup_window,  
  4.                mLayoutBottom, false);  
  5.        int popupHeight = (int) (this.getResources().getDisplayMetrics().heightPixels * 0.75f);  
  6.        mFolderWindow = new PopupWindow(rootView, LinearLayout.LayoutParams.MATCH_PARENT, popupHeight);  
  7.        mFolderWindow.setOutsideTouchable(true);  
  8.        mFolderWindow.setFocusable(true);  
  9.        mFolderWindow.setAnimationStyle(R.style.popup_window_anim);  
  10.        // 在PopupWindow隐藏后,将背景恢复正常亮度  
  11.        mFolderWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {  
  12.            @Override  
  13.            public void onDismiss() {  
  14.                lightOn();  
  15.            }  
  16.        });  
  17.   
  18.        // 文件夹列表初始化  
  19.        mFolderBeans = new ArrayList<>();  
  20.        RecyclerView folderListView = (RecyclerView) rootView.findViewById(R.id.recycler_view);  
  21.        folderListView.setLayoutManager(new LinearLayoutManager(this));  
  22.        mFolderAdapter = new RecycleViewAdapter<FolderBean>(this, mFolderBeans) {  
  23.            @Override  
  24.            public int setItemLayoutId(int position) {  
  25.                return R.layout.item_folder;  
  26.            }  
  27.   
  28.            @Override  
  29.            public void bindView(RViewHolder holder, int position) {  
  30.                String name = mFolderBeans.get(position).getName();  
  31.                int size = mFolderBeans.get(position).getImageList().size();  
  32.                boolean selected = mFolderBeans.get(position).isSelected();  
  33.                ImageBean image = mFolderBeans.get(position).getImageList().get(0);  
  34.   
  35.                holder.setText(R.id.tv_folder_name, name);  
  36.                holder.setText(R.id.tv_image_count, String.valueOf(size) + " 张");  
  37.                holder.setVisible(R.id.iv_sel_status, selected);  
  38.                ImageView imageView = holder.getImageView(R.id.iv_cover);  
  39.                Glide.with(PhotoSelectActivity.this)  
  40.                        .load(image.getPath()).diskCacheStrategy(DiskCacheStrategy.ALL)  
  41.                        .error(R.drawable.bg_img_defalut)  
  42.                        .into(imageView);  
  43.            }  
  44.        };  
  45.   
  46.        mFolderAdapter.setItemClickListener(new OnItemClickListener() {  
  47.            @Override  
  48.            public void onItemClick(RViewHolder holder, int position) {  
  49.                // 如果选择了新的文件夹  
  50.                if (position != mSelFolderIndex) {  
  51.                    // 将上个文件夹的选择状态去除  
  52.                    mFolderBeans.get(mSelFolderIndex).setSelected(false);  
  53.                    mFolderAdapter.notifyItemChanged(mSelFolderIndex);  
  54.                    // 将选择的文件夹做更新  
  55.                    mFolderBeans.get(position).setSelected(true);  
  56.                    mFolderAdapter.notifyItemChanged(position);  
  57.   
  58.                    // 保存当前选择的文件夹  
  59.                    mSelFolderIndex = position;  
  60.                    mSelectedFolder = mFolderBeans.get(position);  
  61.                    mTvFolderName.setText(mSelectedFolder.getName());  
  62.   
  63.                    // 关闭弹窗并更新图片列表  
  64.                    updateImageList();  
  65.                }  
  66.                hidePopup();  
  67.            }  
  68.        });  
  69.        folderListView.setAdapter(mFolderAdapter);  
  70.    }  

4.loadImageData主要用于加载手机照片数据(另一个线程,在上周写的ImageUtils中实现)

[java] view plain copy
  1. private void loadImageData() {  
  2.        ImageUtils.loadImageList(thisnew ImageUtils.OnLoadImageCallBack() {  
  3.            @Override  
  4.            public void callBack(List<FolderBean> folderList) {  
  5.                if (folderList.isEmpty()) {  
  6.                    Toast.makeText(PhotoSelectActivity.this,  
  7.                            "无照片~",Toast.LENGTH_SHORT).show();  
  8.                } else {  
  9.                    mSelectedFolder = folderList.get(0);  
  10.                    mSelFolderIndex = 0;  
  11.                    folderList.get(0).setSelected(true);  
  12.                    mFolderBeans.clear();  
  13.                    mFolderBeans.addAll(folderList);  
  14.   
  15.                    // 加载数据在子线程完成的,需要使用mHandler去通知主线程跟新 UI  
  16.                    mHandler.sendEmptyMessage(0x100);  
  17.                }  
  18.            }  
  19.        });  
  20.    }  

mHandler通知主线程后,要处理Message

[java] view plain copy
  1. @SuppressLint("HandlerLeak")  
  2.    private class MyHandler extends Handler {  
  3.        @Override  
  4.        public void handleMessage(Message msg) {  
  5.            super.handleMessage(msg);  
  6.            if (msg.what == 0x100) {  
  7.                mFolderAdapter.notifyDataSetChanged();  
  8.                updateImageList();  
  9.                // 有照片,可以点击  
  10.                mTvFolderName.setClickable(true);  
  11.            }  
  12.        }  
  13.    }  
[java] view plain copy
  1. /** 
  2.      * 根据选择的文件夹,更新图片列表 
  3.      */  
  4.     private void updateImageList() {  
  5.         mImageBeans.clear();  
  6.         mImageBeans.addAll(mSelectedFolder.getImageList());  
  7.         mImageAdapter.notifyDataSetChanged();  
  8.     }  

5.OnClickListener的具体实现

[java] view plain copy
  1. @Override  
  2.     public void onClick(View v) {  
  3.         if (v.getId() == R.id.tv_folder_name) {  
  4.             if (mFolderWindow.isShowing()) {  
  5.                 hidePopup();  
  6.             } else {  
  7.                 showPopup();  
  8.             }  
  9.         } else if (v.getId() == R.id.iv_back) {  
  10.            this.setResult(RESULT_CANCELED);  
  11.            this.finish();  
  12.         } else if (v.getId() == R.id.tv_send) {  
  13.             sendImage();  
  14.         } else if (v.getId() == R.id.tv_preview) {  
  15.             previewByBtn();  
  16.         } else if (v.getId() == R.id.btn_source_img) {  
  17.             if (mBtnSource.isChecked()) {  
  18.                 mBtnSource.setChecked(false);  
  19.                 isSourceImage = false;  
  20.             } else {  
  21.                 mBtnSource.setChecked(true);  
  22.                 isSourceImage = true;  
  23.             }  
  24.         }  
  25.     }  
[java] view plain copy
  1. /** 
  2.      * 显示和隐藏文件夹选择框 显示在底部布局之上 
  3.      */  
  4.     private void showPopup() {  
  5.         int[] location = new int[2];  
  6.         mLayoutBottom.getLocationOnScreen(location);  
  7.         mFolderWindow.showAtLocation(mLayoutBottom, Gravity.NO_GRAVITY, location[0],  
  8.                 location[1] - mFolderWindow.getHeight());  
  9.         lightOff();  
  10.     }  
  11.   
  12.     private void hidePopup() {  
  13.         mFolderWindow.dismiss();  
  14.     }  
  15.   
  16.     /** 
  17.      *  popupWindow 显示的时候 将图片列表区域变暗 
  18.      *  popupWindow 隐藏的时候恢复 
  19.      */  
  20.   
  21.     private void lightOn(){  
  22.         WindowManager.LayoutParams attributes = getWindow().getAttributes();  
  23.         attributes.alpha = 1.0f;  
  24.         getWindow().setAttributes(attributes);  
  25.     }  
  26.   
  27.     private void lightOff(){  
  28.         WindowManager.LayoutParams attributes = getWindow().getAttributes();  
  29.         attributes.alpha = 0.3f;  
  30.         getWindow().setAttributes(attributes);  
  31.     }  

6.图片显示RecycleView所用的ItemDecoration


[java] view plain copy
  1. public class GridItemDecoration extends RecyclerView.ItemDecoration {  
  2.   
  3.     private static final int[] ATTRS = new int[] { android.R.attr.listDivider };  
  4.     private Drawable mDivider;  
  5.   
  6.     public GridItemDecoration(Context context) {  
  7.         final TypedArray a = context.obtainStyledAttributes(ATTRS);  
  8.         mDivider = a.getDrawable(0);  
  9.         a.recycle();  
  10.     }  
  11.   
  12.     @Override  
  13.     public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
  14.         drawHorizontal(c, parent);  
  15.         drawVertical(c, parent);  
  16.     }  
  17.   
  18.     private int getSpanCount(RecyclerView parent) {  
  19.         // 列数  
  20.         int spanCount = -1;  
  21.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  22.         if (layoutManager instanceof GridLayoutManager) {  
  23.   
  24.             spanCount = ((GridLayoutManager) layoutManager).getSpanCount();  
  25.         } else if (layoutManager instanceof StaggeredGridLayoutManager) {  
  26.             spanCount = ((StaggeredGridLayoutManager) layoutManager)  
  27.                     .getSpanCount();  
  28.         }  
  29.         return spanCount;  
  30.     }  
  31.   
  32.     private void drawHorizontal(Canvas c, RecyclerView parent) {  
  33.         int childCount = parent.getChildCount();  
  34.         for (int i = 0; i < childCount; i++) {  
  35.             final View child = parent.getChildAt(i);  
  36.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  37.                     .getLayoutParams();  
  38.             final int left = child.getLeft() - params.leftMargin;  
  39.             final int right = child.getRight() + params.rightMargin  
  40.                     + mDivider.getIntrinsicWidth();  
  41.             final int top = child.getBottom() + params.bottomMargin;  
  42.             final int bottom = top + mDivider.getIntrinsicHeight();  
  43.             mDivider.setBounds(left, top, right, bottom);  
  44.             mDivider.draw(c);  
  45.         }  
  46.     }  
  47.   
  48.     private void drawVertical(Canvas c, RecyclerView parent) {  
  49.         final int childCount = parent.getChildCount();  
  50.         for (int i = 0; i < childCount; i++) {  
  51.             final View child = parent.getChildAt(i);  
  52.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  53.                     .getLayoutParams();  
  54.             final int top = child.getTop() - params.topMargin;  
  55.             final int bottom = child.getBottom() + params.bottomMargin;  
  56.             final int left = child.getRight() + params.rightMargin;  
  57.             final int right = left + mDivider.getIntrinsicWidth();  
  58.   
  59.             mDivider.setBounds(left, top, right, bottom);  
  60.             mDivider.draw(c);  
  61.         }  
  62.     }  
  63.   
  64.     private boolean isLastColumn(RecyclerView parent, int pos, int spanCount, int childCount) {  
  65.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  66.         if (layoutManager instanceof GridLayoutManager) {  
  67.             // 如果是最后一列,则不需要绘制右边  
  68.             if ((pos + 1) % spanCount == 0) {  
  69.                 return true;  
  70.             }  
  71.         } else if (layoutManager instanceof StaggeredGridLayoutManager) {  
  72.             int orientation = ((StaggeredGridLayoutManager) layoutManager)  
  73.                     .getOrientation();  
  74.             if (orientation == StaggeredGridLayoutManager.VERTICAL) {  
  75.                 // 如果是最后一列,则不需要绘制右边  
  76.                 if ((pos + 1) % spanCount == 0) {  
  77.                     return true;  
  78.                 }  
  79.             } else {  
  80.                 childCount = childCount - childCount % spanCount;  
  81.                 if (pos >= childCount)// 如果是最后一列,则不需要绘制右边  
  82.                     return true;  
  83.             }  
  84.         }  
  85.         return false;  
  86.     }  
  87.   
  88.     private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) {  
  89.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  90.         if (layoutManager instanceof GridLayoutManager) {  
  91.             childCount = childCount - childCount % spanCount;  
  92.             if (pos >= childCount)// 如果是最后一行,则不需要绘制底部  
  93.                 return true;  
  94.         } else if (layoutManager instanceof StaggeredGridLayoutManager) {  
  95.             int orientation = ((StaggeredGridLayoutManager) layoutManager)  
  96.                     .getOrientation();  
  97.             // StaggeredGridLayoutManager 且纵向滚动  
  98.             if (orientation == StaggeredGridLayoutManager.VERTICAL) {  
  99.                 childCount = childCount - childCount % spanCount;  
  100.                 // 如果是最后一行,则不需要绘制底部  
  101.                 if (pos >= childCount)  
  102.                     return true;  
  103.             } else {   // StaggeredGridLayoutManager 且横向滚动  
  104.                 // 如果是最后一行,则不需要绘制底部  
  105.                 if ((pos + 1) % spanCount == 0) {  
  106.                     return true;  
  107.                 }  
  108.             }  
  109.         }  
  110.         return false;  
  111.     }  
  112.   
  113.   
  114.     @Override  
  115.     public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {  
  116.         int spanCount = getSpanCount(parent);  
  117.         int childCount = parent.getAdapter().getItemCount();  
  118.         if (isLastRaw(parent, itemPosition, spanCount, childCount)){ // 如果是最后一行,则不需要绘制底部  
  119.             outRect.set(00, mDivider.getIntrinsicWidth(), 0);  
  120.         } else if (isLastColumn(parent, itemPosition, spanCount, childCount)){// 如果是最后一列,则不需要绘制右边  
  121.             outRect.set(000, mDivider.getIntrinsicHeight());  
  122.         } else {  
  123.             outRect.set(00, mDivider.getIntrinsicWidth(),  
  124.                     mDivider.getIntrinsicHeight());  
  125.         }  
  126.     }  
  127.   
  128. }  



仝心:

       这几天主要在实现录音功能。

        首先自定义了一个音频记录管理器AudioRecordManager用于录音,定义prepareAudio方法,用于设置输出路径,音频源、麦克风,输出格式和音频编码。

[java] view plain copy
  1. public void prepareAudio(){  
  2.         try {  
  3.             hasPrepare = false;  
  4.             File dir = new File(mAudioDir);  
  5.             if (!dir.exists()){  
  6.                 dir.mkdirs();  
  7.             }  
  8.             mMediaRecorder = new MediaRecorder();  
  9.             String fileName = UUID.randomUUID().toString() + ".arm";  
  10.             File file = new File(dir,fileName);  
  11.             mCurrentFilePath = file.getAbsolutePath();  
  12.             // 设置输出路径  
  13.             mMediaRecorder.setOutputFile(mCurrentFilePath);  
  14.             // 设置音频源,麦克风  
  15.             mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  
  16.             // 设置输出格式  
  17.             mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);  
  18.             // 设置音频编码  
  19.             mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  
  20.             // 准备  
  21.             mMediaRecorder.prepare();  
  22.             mMediaRecorder.start();  
  23.             hasPrepare = true;  
  24.   
  25.             if (mStateListener != null){  
  26.                 mStateListener.prepareFinish(mCurrentFilePath);  
  27.             }  
  28.         } catch (IOException e) {  
  29.             if (mStateListener != null){  
  30.                 mStateListener.prepareError(e.getMessage());  
  31.             }  
  32.             e.printStackTrace();  
  33.         }  
  34.   
  35.     }  

    接下来获取音量等级,等级上限作为参数传入

[java] view plain copy
  1. public int getVoiceLevel(int maxLevel){  
  2.         try {  
  3.             if (hasPrepare){  
  4.                 // getMaxAmplitude = 0 - 32767  
  5.                 return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;  
  6.             }  
  7.         }catch (Exception e){  
  8.             return 1;  
  9.         }  
  10.         return 1;  
  11.     }  
[java] view plain copy
  1. public void releaseAudio(){  
  2.         mMediaRecorder.stop();  
  3.         mMediaRecorder.release();  
  4.         mMediaRecorder = null;  
  5.         hasPrepare = false;  
  6.     }  
  7.   
  8.     public void cancelAudio(){  
  9.         releaseAudio();  
  10.         if (mCurrentFilePath != null){  
  11.             File file = new File(mCurrentFilePath);  
  12.             file.delete();  
  13.         }  
  14.     }      

      接下来定义音频对话管理器AudioDialogManager类用于在和好友的对话中发送录音。

[java] view plain copy
  1.     private Context mContext;  
  2.     private Dialog mDialog;  
  3.     private LayoutInflater mInflater;  
  4.     private ImageView mIvRecord;  
  5.     private ImageView mIvVoiceLevel;  
  6.     private TextView mTvTip;  
  7.   
  8.     public RecordDialogManager(Context context){  
  9.         mContext = context;  
  10.         mInflater = LayoutInflater.from(mContext);  
  11.     }  

    显示之前的消息记录中的录音的方法:

[java] view plain copy
  1. public void showDialogRecord(){  
  2.         View view = mInflater.inflate(R.layout.dialog_audio_record_button,null);  
  3.         mDialog = new Dialog(mContext, R.style.Theme_Audio_Record_Button);  
  4.         mDialog.setContentView(view);  
  5.         mIvRecord = (ImageView) mDialog.findViewById(R.id.iv_record);  
  6.         mIvVoiceLevel = (ImageView) mDialog.findViewById(R.id.iv_voice_level);  
  7.         mTvTip = (TextView) mDialog.findViewById(R.id.tv_dialog_tip);  
  8.         mDialog.show();  
  9.     }  

    在聊天中发送录音的操作指示,包括取消发送、提示录音时间过短、取消发送

[java] view plain copy
  1. public void showRecording(){  
  2.         if (mDialog != null && mDialog.isShowing()){  
  3.             mIvRecord.setImageResource(R.drawable.recorder);  
  4.             mIvVoiceLevel.setVisibility(View.VISIBLE);  
  5.             mTvTip.setText(mContext.getString(R.string.move_up_cancel));  
  6.         }  
  7.     }  
  8.   
  9.     public void showDialogToShort(){  
  10.         if (mDialog != null && mDialog.isShowing()){  
  11.             mIvRecord.setImageResource(R.drawable.voice_to_short);  
  12.             mIvVoiceLevel.setVisibility(View.GONE);  
  13.             mTvTip.setText(mContext.getString(R.string.record_to_short));  
  14.         }  
  15.     }  
  16.   
  17.     public void showDialogWantCancel(){  
  18.         if (mDialog != null && mDialog.isShowing()){  
  19.             mIvRecord.setImageResource(R.drawable.cancel);  
  20.             mIvVoiceLevel.setVisibility(View.GONE);  
  21.             mTvTip.setText(mContext.getString(R.string.release_cancel));  
  22.         }  
  23.     }  
    根据音量大小更新音量图标高度
[java] view plain copy
  1. public void updateVoiceLevel(int level){  
  2.         if (mDialog != null && mDialog.isShowing()){  
  3.             int resId = mContext.getResources().getIdentifier("v"+level,  
  4.                     "drawable",mContext.getPackageName());  
  5.             mIvVoiceLevel.setImageResource(resId);  
  6.         }  
  7.     }  



张静:

本周我完成了ContractFragment中点击“添加朋友”和“验证提醒”后分别会跳转进入的界面以及相关功能实现

一. SearchUserActivity(根据账户搜索用户)—— 点击“添加朋友”后跳转入的

1. activity_search_user.xml

[java] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:orientation="vertical"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:fitsSystemWindows="true">  
  8.   
  9.     <include layout="@layout/title_layout"/>  
  10.   
  11.     <LinearLayout  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:layout_marginLeft="10dp"  
  15.         android:layout_marginRight="10dp">  
  16.         <EditText  
  17.             android:id="@+id/et_user_account"  
  18.             android:paddingLeft="5dp"  
  19.             android:paddingRight="5dp"  
  20.             android:layout_width="0dp"  
  21.             android:layout_weight="1"  
  22.             android:layout_height="45dp"  
  23.             android:background="@drawable/et_back_ground"  
  24.             android:textColorHint="@color/hint_color"  
  25.             android:hint="@string/please_input_account"/>  
  26.   
  27.         <ImageView  
  28.             android:id="@+id/iv_search"  
  29.             android:layout_marginTop="5dp"  
  30.             android:background="@color/app_blue_color"  
  31.             android:layout_width="40dp"  
  32.             android:layout_height="40dp"  
  33.             android:src="@mipmap/search"/>  
  34.     </LinearLayout>  
  35.   
  36.   
  37.   
  38.   
  39. </LinearLayout>  


2. 初始化回调

有三种情况:

(1)成功:

       a.若找不到该账户,显示消息“查无此人哦,请检查后再试~”

       b.若成功找到,跳转到FriendInfoActivity,上周博客写过该Activity,同时设置flag为FLAG_ADD_FRIEND,即显示的该账户只能

          选择添加到通讯录,没有发送消息和视频聊天选项

(2)失败:显示消息“搜索失败,返回码:xxx”

(3)出错:显示消息“搜索出错”

[java] view plain copy
  1. private void initCallBack(){  
  2.         mRequestCallback = new RequestCallback<List<NimUserInfo>>() {  
  3.   
  4.             @Override  
  5.             public void onSuccess(List<NimUserInfo> param) {  
  6.                 if (param.isEmpty()){  
  7.                     ToastUtils.showMessage(SearchUserActivity.this,"查无此人喔,请检查后再试~~");  
  8.                     return;  
  9.                 }  
  10.                 Intent intent = new Intent(SearchUserActivity.this,FriendInfoActivity.class);  
  11.                 intent.putExtra("FLAG",FriendInfoActivity.FLAG_ADD_FRIEND);  
  12.                 intent.putExtra("NimUserInfo",param.get(0));  
  13.                 startActivity(intent);  
  14.             }  
  15.   
  16.             @Override  
  17.             public void onFailed(int code) {  
  18.                 ToastUtils.showMessage(SearchUserActivity.this,"搜索失败,返回码:" + code);  
  19.             }  
  20.   
  21.             @Override  
  22.             public void onException(Throwable exception) {  
  23.                 ToastUtils.showMessage(SearchUserActivity.this,"搜索出错:" + exception.getMessage());  
  24.             }  
  25.         };  
  26.     }  

ToastUtils.java

[java] view plain copy
  1. package com.ezreal.ezchat.commonlibrary.utils;  
  2.   
  3. import android.content.Context;  
  4. import android.os.Handler;  
  5. import android.os.Looper;  
  6. import android.widget.Toast;  
  7.   
  8. /** 
  9.  *  Created by 张静 
  10.  */  
  11. public class ToastUtils {  
  12.     private static Handler handler = new Handler(Looper.getMainLooper());  
  13.   
  14.   
  15.   
  16.     public static void showMessage(final Context context, final String msg) {  
  17.         showMessage(context, msg, Toast.LENGTH_SHORT);  
  18.     }  
  19.   
  20.     private static void showMessage(final Context act, final String msg,  
  21.                                    final int len) {  
  22.        handler.post(new Runnable() {  
  23.            @Override  
  24.            public void run() {  
  25.                Toast.makeText(act,msg,len).show();  
  26.            }  
  27.        });  
  28.     }  
  29.   
  30. }  


3. 查询朋友

若检测到的所查询的账号为空或者是自己的账号,都会提示,无法成功查询

通过NimClient的getService接口获取到UserService(用户资料操作相关接口)服务实例,调用fetchUserInfo方法从服务器获取用户资料

[java] view plain copy
  1. @OnClick(R.id.iv_search)  
  2.     public void searchFriend(){  
  3.         String account = mEtUserAccount.getText().toString().trim();  
  4.         if (TextUtils.isEmpty(account)){  
  5.             ToastUtils.showMessage(SearchUserActivity.this,"账号不能为空");  
  6.             return;  
  7.         }  
  8.         if (account.equals(NimUserHandler.getInstance().getMyAccount())){  
  9.             ToastUtils.showMessage(SearchUserActivity.this,"不能添加自己为好友");  
  10.             return;  
  11.         }  
  12.         List<String> accounts = new ArrayList<>(1);  
  13.         accounts.add(account);  
  14.         NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(mRequestCallback);  
  15.     }  

4. 返回

[java] view plain copy
  1. @OnClick(R.id.iv_back_btn)  
  2.     public void backOnClick(){  
  3.         finish();  
  4.     }  


附上完整 SearchUserActivity.java

[java] view plain copy
  1. package com.ezreal.ezchat.activity;  
  2.   
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.support.annotation.Nullable;  
  6. import android.text.TextUtils;  
  7. import android.widget.EditText;  
  8.   
  9. import com.ezreal.ezchat.R;  
  10. import com.ezreal.ezchat.handler.NimUserHandler;  
  11. import com.netease.nimlib.sdk.NIMClient;  
  12. import com.netease.nimlib.sdk.RequestCallback;  
  13. import com.netease.nimlib.sdk.uinfo.UserService;  
  14. import com.netease.nimlib.sdk.uinfo.model.NimUserInfo;  
  15. import com.ezreal.ezchat.commonlibrary.utils.ToastUtils;  
  16.   
  17. import java.util.ArrayList;  
  18. import java.util.List;  
  19.   
  20. import butterknife.BindView;  
  21. import butterknife.ButterKnife;  
  22. import butterknife.OnClick;  
  23.   
  24. /** 
  25.  * 根据账户搜索用户 
  26.  * Created by 张静 
  27.  */  
  28.   
  29. public class SearchUserActivity extends BaseActivity {  
  30.   
  31.     @BindView(R.id.et_user_account)  
  32.     EditText mEtUserAccount;  
  33.   
  34.     private static final String TAG = SearchUserActivity.class.getSimpleName();  
  35.   
  36.     private RequestCallback<List<NimUserInfo>> mRequestCallback;  
  37.     @Override  
  38.     protected void onCreate(@Nullable Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setStatusBarColor(R.color.app_blue_color);  
  41.         setContentView(R.layout.activity_search_user);  
  42.         setTitleBar("添加朋友",true,false);  
  43.         ButterKnife.bind(this);  
  44.         initCallBack();  
  45.     }  
  46.   
  47.     private void initCallBack(){  
  48.         mRequestCallback = new RequestCallback<List<NimUserInfo>>() {  
  49.   
  50.             @Override  
  51.             public void onSuccess(List<NimUserInfo> param) {  
  52.                 if (param.isEmpty()){  
  53.                     ToastUtils.showMessage(SearchUserActivity.this,"查无此人喔,请检查后再试~~");  
  54.                     return;  
  55.                 }  
  56.                 Intent intent = new Intent(SearchUserActivity.this,FriendInfoActivity.class);  
  57.                 intent.putExtra("FLAG",FriendInfoActivity.FLAG_ADD_FRIEND);  
  58.                 intent.putExtra("NimUserInfo",param.get(0));  
  59.                 startActivity(intent);  
  60.             }  
  61.   
  62.             @Override  
  63.             public void onFailed(int code) {  
  64.                 ToastUtils.showMessage(SearchUserActivity.this,"搜索失败,返回码:" + code);  
  65.             }  
  66.   
  67.             @Override  
  68.             public void onException(Throwable exception) {  
  69.                 ToastUtils.showMessage(SearchUserActivity.this,"搜索出错:" + exception.getMessage());  
  70.             }  
  71.         };  
  72.     }  
  73.   
  74.     @OnClick(R.id.iv_search)  
  75.     public void searchFriend(){  
  76.         String account = mEtUserAccount.getText().toString().trim();  
  77.         if (TextUtils.isEmpty(account)){  
  78.             ToastUtils.showMessage(SearchUserActivity.this,"账号不能为空");  
  79.             return;  
  80.         }  
  81.         if (account.equals(NimUserHandler.getInstance().getMyAccount())){  
  82.             ToastUtils.showMessage(SearchUserActivity.this,"不能添加自己为好友");  
  83.             return;  
  84.         }  
  85.         List<String> accounts = new ArrayList<>(1);  
  86.         accounts.add(account);  
  87.         NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(mRequestCallback);  
  88.     }  
  89.   
  90.     @OnClick(R.id.iv_back_btn)  
  91.     public void backOnClick(){  
  92.         finish();  
  93.     }  
  94.   
  95. }  

阅读更多
上一篇实训第四周(2)
下一篇实训第五周(2)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭