实训第五周(1)

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

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

     

主要内容如下

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo_selector);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);//弹出一个窗口,让背后的窗口变暗一点
        initView();
        initImageList();
        initPopupWindow();
        loadImageData();
    }

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

private void initView() {
        mImageListView = (RecyclerView) findViewById(R.id.recycler_view);
        mBtnSource = (RadioButton) findViewById(R.id.btn_source_img);
        mTvFolderName = (TextView) findViewById(R.id.tv_folder_name);
        mTvPreview = (TextView) findViewById(R.id.tv_preview);
        mIvBack = (ImageView) findViewById(R.id.iv_back);
        mTvSend = (TextView) findViewById(R.id.tv_send);

        mLayoutBottom = (RelativeLayout) findViewById(R.id.layout_bottom);

        mIvBack.setOnClickListener(this);
        mTvSend.setOnClickListener(this);
        mTvFolderName.setOnClickListener(this);
        mTvPreview.setOnClickListener(this);
        mBtnSource.setOnClickListener(this);

        // 文件选择按钮,只有在加载数据完成并且数据不为空的时候才可以点击
        mTvFolderName.setClickable(false);
        // 发送和预览按钮只有在有照片选择的情况下才可以点击
        mTvPreview.setClickable(false);
        mTvSend.setClickable(false);
    }

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

private void initImageList() {
        mImageBeans = new ArrayList<>();
        mImageListView.setLayoutManager(new GridLayoutManager(this, 3));
        mImageListView.addItemDecoration(new GridItemDecoration(this));
        mImageAdapter = new RecycleViewAdapter<ImageBean>(this, mImageBeans) {
            @Override
            public int setItemLayoutId(int position) {
                return R.layout.item_image_sel;
            }

            @Override
            public void bindView(RViewHolder holder, final int position) {
                // 使用Glide加载照片,它有缓存策略,避免 OOM
                final ImageBean item = mImageBeans.get(position);
                ImageView imageView = holder.getImageView(R.id.iv_img);//有就拿到,没有就先加入RViewHolder的mViews列表再返回
                Glide.with(PhotoSelectActivity.this)
                        .load(item.getPath()).diskCacheStrategy(DiskCacheStrategy.ALL)
                        .error(R.drawable.bg_img_defalut)
                        .into(imageView);

                // 单击照片本身,在预览窗口打开该照片
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mShowItem = item;
                        previewByItem();
                    }
                });

                // 照片右上角的选择器,根据照片被选择与否显示不同状态 icon
                final RadioButton radioButton = (RadioButton) holder.getConvertView()
                        .findViewById(R.id.img_sel_status);
                radioButton.setChecked(item.isSelected());

                // 选择框单击事件监听,用于更新照片选择状态
                radioButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ImageBean imageBean = mImageBeans.get(position);
                        if (imageBean.isSelected()) {
                            radioButton.setChecked(false);
                            imageBean.setSelected(false);
                            mSelectedImages.remove(imageBean);
                            updateBtnState();
                        } else if (mSelectedImages.size() < 9) {
                            radioButton.setChecked(true);
                            imageBean.setSelected(true);
                            mSelectedImages.add(imageBean);
                            updateBtnState();
                        } else {
                            radioButton.setChecked(false);
                            Toast.makeText(PhotoSelectActivity.this,
                                    "一次只能选择9张喔~",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        };
        mImageListView.setAdapter(mImageAdapter);
    }

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

private void updateBtnState() {
        String size = String.valueOf(mSelectedImages.size());
        String tvSend = "发送(" + size + "/9)";
        String tvPre = "预览(" + size + "/9)";
        mTvSend.setText(tvSend);
        mTvPreview.setText(tvPre);

        if (mSelectedImages.isEmpty()) {
            mTvSend.setClickable(false);
            mTvSend.setTextColor(getResources().getColor(R.color.blue_gray));

            mTvPreview.setClickable(false);
            mTvPreview.setTextColor(getResources().getColor(R.color.blue_gray));
        } else {
            mTvSend.setClickable(true);
            mTvSend.setTextColor(getResources().getColor(R.color.colorAccent));

            mTvPreview.setClickable(true);
            mTvPreview.setTextColor(getResources().getColor(R.color.colorAccent));
        }
    }

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

 private void initPopupWindow() {
        // 弹窗初始化,高度设置为屏幕的 3/4
        View rootView = LayoutInflater.from(this).inflate(R.layout.popup_window,
                mLayoutBottom, false);
        int popupHeight = (int) (this.getResources().getDisplayMetrics().heightPixels * 0.75f);
        mFolderWindow = new PopupWindow(rootView, LinearLayout.LayoutParams.MATCH_PARENT, popupHeight);
        mFolderWindow.setOutsideTouchable(true);
        mFolderWindow.setFocusable(true);
        mFolderWindow.setAnimationStyle(R.style.popup_window_anim);
        // 在PopupWindow隐藏后,将背景恢复正常亮度
        mFolderWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                lightOn();
            }
        });

        // 文件夹列表初始化
        mFolderBeans = new ArrayList<>();
        RecyclerView folderListView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
        folderListView.setLayoutManager(new LinearLayoutManager(this));
        mFolderAdapter = new RecycleViewAdapter<FolderBean>(this, mFolderBeans) {
            @Override
            public int setItemLayoutId(int position) {
                return R.layout.item_folder;
            }

            @Override
            public void bindView(RViewHolder holder, int position) {
                String name = mFolderBeans.get(position).getName();
                int size = mFolderBeans.get(position).getImageList().size();
                boolean selected = mFolderBeans.get(position).isSelected();
                ImageBean image = mFolderBeans.get(position).getImageList().get(0);

                holder.setText(R.id.tv_folder_name, name);
                holder.setText(R.id.tv_image_count, String.valueOf(size) + " 张");
                holder.setVisible(R.id.iv_sel_status, selected);
                ImageView imageView = holder.getImageView(R.id.iv_cover);
                Glide.with(PhotoSelectActivity.this)
                        .load(image.getPath()).diskCacheStrategy(DiskCacheStrategy.ALL)
                        .error(R.drawable.bg_img_defalut)
                        .into(imageView);
            }
        };

        mFolderAdapter.setItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(RViewHolder holder, int position) {
                // 如果选择了新的文件夹
                if (position != mSelFolderIndex) {
                    // 将上个文件夹的选择状态去除
                    mFolderBeans.get(mSelFolderIndex).setSelected(false);
                    mFolderAdapter.notifyItemChanged(mSelFolderIndex);
                    // 将选择的文件夹做更新
                    mFolderBeans.get(position).setSelected(true);
                    mFolderAdapter.notifyItemChanged(position);

                    // 保存当前选择的文件夹
                    mSelFolderIndex = position;
                    mSelectedFolder = mFolderBeans.get(position);
                    mTvFolderName.setText(mSelectedFolder.getName());

                    // 关闭弹窗并更新图片列表
                    updateImageList();
                }
                hidePopup();
            }
        });
        folderListView.setAdapter(mFolderAdapter);
    }

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

 private void loadImageData() {
        ImageUtils.loadImageList(this, new ImageUtils.OnLoadImageCallBack() {
            @Override
            public void callBack(List<FolderBean> folderList) {
                if (folderList.isEmpty()) {
                    Toast.makeText(PhotoSelectActivity.this,
                            "无照片~",Toast.LENGTH_SHORT).show();
                } else {
                    mSelectedFolder = folderList.get(0);
                    mSelFolderIndex = 0;
                    folderList.get(0).setSelected(true);
                    mFolderBeans.clear();
                    mFolderBeans.addAll(folderList);

                    // 加载数据在子线程完成的,需要使用mHandler去通知主线程跟新 UI
                    mHandler.sendEmptyMessage(0x100);
                }
            }
        });
    }

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

 @SuppressLint("HandlerLeak")
    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0x100) {
                mFolderAdapter.notifyDataSetChanged();
                updateImageList();
                // 有照片,可以点击
                mTvFolderName.setClickable(true);
            }
        }
    }
/**
     * 根据选择的文件夹,更新图片列表
     */
    private void updateImageList() {
        mImageBeans.clear();
        mImageBeans.addAll(mSelectedFolder.getImageList());
        mImageAdapter.notifyDataSetChanged();
    }

5.OnClickListener的具体实现

@Override
    public void onClick(View v) {
        if (v.getId() == R.id.tv_folder_name) {
            if (mFolderWindow.isShowing()) {
                hidePopup();
            } else {
                showPopup();
            }
        } else if (v.getId() == R.id.iv_back) {
           this.setResult(RESULT_CANCELED);
           this.finish();
        } else if (v.getId() == R.id.tv_send) {
            sendImage();
        } else if (v.getId() == R.id.tv_preview) {
            previewByBtn();
        } else if (v.getId() == R.id.btn_source_img) {
            if (mBtnSource.isChecked()) {
                mBtnSource.setChecked(false);
                isSourceImage = false;
            } else {
                mBtnSource.setChecked(true);
                isSourceImage = true;
            }
        }
    }
/**
     * 显示和隐藏文件夹选择框 显示在底部布局之上
     */
    private void showPopup() {
        int[] location = new int[2];
        mLayoutBottom.getLocationOnScreen(location);
        mFolderWindow.showAtLocation(mLayoutBottom, Gravity.NO_GRAVITY, location[0],
                location[1] - mFolderWindow.getHeight());
        lightOff();
    }

    private void hidePopup() {
        mFolderWindow.dismiss();
    }

    /**
     *  popupWindow 显示的时候 将图片列表区域变暗
     *  popupWindow 隐藏的时候恢复
     */

    private void lightOn(){
        WindowManager.LayoutParams attributes = getWindow().getAttributes();
        attributes.alpha = 1.0f;
        getWindow().setAttributes(attributes);
    }

    private void lightOff(){
        WindowManager.LayoutParams attributes = getWindow().getAttributes();
        attributes.alpha = 0.3f;
        getWindow().setAttributes(attributes);
    }

6.图片显示RecycleView所用的ItemDecoration

mImageListView.addItemDecoration(new GridItemDecoration(this));

public class GridItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
    private Drawable mDivider;

    public GridItemDecoration(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        drawHorizontal(c, parent);
        drawVertical(c, parent);
    }

    private int getSpanCount(RecyclerView parent) {
        // 列数
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    private void drawHorizontal(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private void drawVertical(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColumn(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            // 如果是最后一列,则不需要绘制右边
            if ((pos + 1) % spanCount == 0) {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                // 如果是最后一列,则不需要绘制右边
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            } else {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            childCount = childCount - childCount % spanCount;
            if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else {   // StaggeredGridLayoutManager 且横向滚动
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }


    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        if (isLastRaw(parent, itemPosition, spanCount, childCount)){ // 如果是最后一行,则不需要绘制底部
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else if (isLastColumn(parent, itemPosition, spanCount, childCount)){// 如果是最后一列,则不需要绘制右边
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
                    mDivider.getIntrinsicHeight());
        }
    }

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值