zl程序教程

您现在的位置是:首页 > 

当前栏目

仿朋友圈相册图片选择以及画廊效果「建议收藏」

建议 收藏 图片 选择 以及 效果 相册 朋友圈
2023-06-13 09:11:43 时间

大家好,又见面了,我是你们的朋友全栈君。

仿朋友圈相册图片选择以及画廊效果

1.效果展示

该demo适配Android 6、7、10。画廊效果,支持缩放效果。 视频展示:

安卓实现仿微信朋友圈以及画廊效果

部分截图:

文章有点长,如果没时间就拉到最底下下载源码,再给个一键三联哈(* ̄︶ ̄)

2.导入相关第三方库依赖

站在巨人的肩膀上,敲代码便可事半功倍。

    //图片加载框架
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    //黄油刀
    implementation 'com.jakewharton:butterknife:10.2.3'
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
    // 图片选择器
    api 'com.zhihu.android:matisse:0.5.3-beta3'
    //动态权限申请
    implementation 'com.yanzhenjie:permission:2.0.3'
    //rv
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    //rv第三方万能适配器
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
    //顶部标题栏
    implementation 'com.wuhenzhizao:titlebar:1.0.7'
    //图片缩放框架
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'

3.编写选择图片页面

a.编写布局

<LinearLayout 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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:orientation="vertical">

    <com.wuhenzhizao.titlebar.widget.CommonTitleBar
        android:id="@+id/title"
        style="@style/StyleTitle"
        app:centerText="@string/wechat_zone"
        app:leftType="none"
        app:showBottomLine="true" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@mipmap/home_bg_float"
        android:orientation="vertical">

        <EditText
            android:id="@+id/et_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:focusable="true"
            android:gravity="top"
            android:hint="@string/hint_text"
            android:lineSpacingExtra="9dp"
            android:lineSpacingMultiplier="1.2"
            android:maxLength="400"
            android:minHeight="200dp"
            android:paddingLeft="15dp"
            android:paddingTop="20dp"
            android:paddingRight="15dp"
            android:paddingBottom="20dp"
            android:textColor="@color/text_primary"
            android:textColorHint="@color/dialog_cancel_text_color"
            android:textSize="13sp" />

        <TextView
            android:id="@+id/tv_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginRight="15dp"
            android:layout_marginBottom="5dp"
            android:text="0/400"
            android:textColor="@color/dialog_cancel_text_color"
            android:textSize="14sp" />

        <View style="@style/StyleLine" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/dp_10" />
    </LinearLayout>

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_margin="@dimen/dp_10"
        android:background="@mipmap/home_bg_float"
        android:text="@string/submit" />
</LinearLayout>

b.编写Activity

public class MainActivity extends AppCompatActivity implements OnItemClickListener, OnItemChildClickListener, TextWatcher { 
   
    @BindView(R.id.rv_photo)
    RecyclerView mRvPhoto;
    @BindView(R.id.activity_main)
    LinearLayout mActivityMain;
    @BindView(R.id.title)
    CommonTitleBar mTitle;
    @BindView(R.id.et_content)
    EditText mEtContent;
    @BindView(R.id.tv_count)
    TextView mTvCount;
    @BindView(R.id.btn_submit)
    Button mBtnSubmit;
    private PhotoAdapter mPhotoAdapter;
    //点击item的时候通过判断是否有照片文件list,有值跳画廊ac,没值弹框
    private List<PhotoVo> mPhotoList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) { 
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initViews();
    }

    private void initViews() { 
   
        mPhotoAdapter = new PhotoAdapter();
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
        mRvPhoto.setLayoutManager(gridLayoutManager);
        mPhotoAdapter.setList(dealWithList(mPhotoList));
        mRvPhoto.setAdapter(mPhotoAdapter);
        mPhotoAdapter.setOnItemClickListener(this);
        mPhotoAdapter.setOnItemChildClickListener(this);
        mEtContent.addTextChangedListener(this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 
   
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) { 
   
            switch (requestCode) { 
   
                case CameraAlbumUtil.REQUEST_CODE_TAKE_PHOTO://相机回调
                    String contentPath = CameraAlbumUtil.getInstance().getCameraPath();
                    mPhotoList.add(new PhotoVo(contentPath, new File(contentPath)));
                    mPhotoAdapter.setList(dealWithList(mPhotoList));
                    break;
                case CameraAlbumUtil.REQUEST_CODE_ALBUM://相册回调
                    List<String> pathList;
                    if (data != null) { 
   
                        pathList = Matisse.obtainPathResult(data);
                        if (pathList.size() > 0) { 
   
                            for (int i = 0; i < pathList.size(); i++) { 
   
                                String s = pathList.get(i);
                                Uri uri = FileUtil.getImageContentUri(this, pathList.get(i));
                                mPhotoList.add(new PhotoVo(s, FileUtil.changeFile(this, uri)));
                            }
                            mPhotoAdapter.setList(dealWithList(mPhotoList));
                        }
                    }

                    break;
            }
        }
    }

    private List<PhotoVo> dealWithList(List<PhotoVo> list) { 
   
        List<PhotoVo> newList = new ArrayList<>();
        if (list != null) newList.addAll(list);
        if (newList.size() < 4) newList.add(null);//最多只能4张
        return newList;
    }

    @Override
    public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view,
                            int position) { 
   
        if (adapter.getData().get(position) == null) { 
   
            CameraAlbumUtil.getInstance().showCameraAlbumDialog(this);
        } else { 
   
            Intent intent = new Intent(this, GalleryActivity.class);
            intent.putExtra("photoList", (Serializable) mPhotoList);
            startActivity(intent);
        }
    }

    @Override
    public void onItemChildClick(@NonNull BaseQuickAdapter adapter, @NonNull View view,
                                 int position) { 
   
        if (view.getId() == R.id.iv_delete) { 
   //删除按钮
            mPhotoList.remove(mPhotoList.get(position));
            mPhotoAdapter.setList(dealWithList(mPhotoList));
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
   

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { 
   

    }

    @Override
    public void afterTextChanged(Editable s) { 
   
        mTvCount.setText(s.length() + "/400");
    }


}

c.相册选择工具类部分代码

/** * @author LJW * @create 2020/11/16 * @Describe 打开相机相册工具类 */
public class CameraAlbumUtil { 
   
    public static final int REQUEST_CODE_TAKE_PHOTO = 1000;
    public static final int REQUEST_CODE_ALBUM = 1001;
    private static final String ALBUM = "ALBUM";
    private static MediaStoreCompat mediaStoreCompat;

    private CameraAlbumUtil() { 
   
    }

    /** * * @param activity */
    public void showCameraAlbumDialog(Activity activity) { 
   
        DialogUtil dialogUtil = new DialogUtil();
        dialogUtil.setClickListenerInterface(new DialogUtil.ClickListenerInterface() { 
   
            @Override
            public void onAlbumClickListener() { 
   
                getPermission(activity, ALBUM, REQUEST_CODE_ALBUM);
            }

            @Override
            public void onCameraClickListener() { 
   
                getPermission(activity, "", REQUEST_CODE_TAKE_PHOTO);
            }
        });
        dialogUtil.showDialog(activity);
    }

    /** * @param activity 哪个界面 * @param type 打开相册传"ALBUM",其他传"" * @param requestCode 请求码 */
    public void getPermission(Activity activity, String type, int requestCode) { 
   
        if (!AndPermission.hasPermissions(activity, Permission.CAMERA, Permission.WRITE_EXTERNAL_STORAGE)) { 
   
            AndPermission.with(activity)
                    .runtime()
                    .permission(Permission.CAMERA, Permission.WRITE_EXTERNAL_STORAGE)
                    .onGranted(permissions -> { 
   
                        switch (type) { 
   
                            case ALBUM:
                                gotoAlbum(activity, requestCode);
                                break;
                            default:
                                gotoCamera(activity, requestCode);
                                break;
                        }
                    })
                    .onDenied(permissions -> { 
   
                    })
                    .start();
        } else { 
   
            switch (type) { 
   
                case ALBUM:
                    gotoAlbum(activity, requestCode);
                    break;
                default:
                    gotoCamera(activity, requestCode);
                    break;
            }
        }
    }

    /** * 打开相机 * * @param activity * @param requestCode 请求码 */
    public void gotoCamera(Activity activity, int requestCode) { 
   
        mediaStoreCompat = new MediaStoreCompat(activity);
        mediaStoreCompat.setCaptureStrategy(new CaptureStrategy(false,
                "com.example.viewpagegallery.fileProvider",
                "preventpro"));
        mediaStoreCompat.dispatchCaptureIntent(activity, requestCode);
    }

    /** * 打开相册 * * @param activity * @param requestCode 请求码 */
    public void gotoAlbum(Activity activity, int requestCode) { 
   
        Matisse.from(activity)
                .choose(MimeType.ofAll())
                .countable(true)
                .maxSelectable(4)
                .gridExpectedSize(activity.getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                .thumbnailScale(0.85f)
                .imageEngine(new GlideEngine())
                .showPreview(false) // Default is `true`
                .capture(false) //是否提供拍照功能
                .captureStrategy(new CaptureStrategy(true, "com.example.viewpagegallery.fileProvider"))//存储到哪里
                .forResult(requestCode);
    }

    /** * 获取拍照后的地址,方便上传使用 * * @return */
    public String getCameraPath() { 
   
        return mediaStoreCompat.getCurrentPhotoPath();
    }

    public static class SingleInstance { 
   
        private static CameraAlbumUtil cameraAlbumSingle = new CameraAlbumUtil();
    }

    public static CameraAlbumUtil getInstance() { 
   
        return SingleInstance.cameraAlbumSingle;
    }
}

d.相册4宫图适配器

public class PhotoAdapter extends BaseQuickAdapter<PhotoVo, BaseViewHolder> { 
   
    public PhotoAdapter() { 
   
        super(R.layout.item_phtoto);
    }

    @Override
    protected void convert(@NotNull BaseViewHolder holder, PhotoVo photoVo) { 
   
        if (photoVo != null && photoVo.getFile() != null) { 
   //空图
            CornerTransform transformation = new CornerTransform(getContext(), ScreenUtils.dip2px(getContext(), 10));
            Glide.with(getContext()).load(photoVo.getFile().getPath())
                    .transform(transformation)
                    .into((ImageView) holder.getView(R.id.iv_img));
            holder.setVisible(R.id.iv_empty, false);
            holder.setVisible(R.id.iv_delete, true);
            holder.setVisible(R.id.iv_img, true);
        } else { 
   //有图
            holder.setVisible(R.id.iv_empty, true);
            holder.setGone(R.id.iv_delete, true);
            holder.setGone(R.id.iv_img, true);
        }

        holder.getView(R.id.iv_delete).setOnClickListener(new View.OnClickListener() { 
   
            @Override
            public void onClick(View v) { 
   
                setOnItemChildClick(v, holder.getAdapterPosition());
            }
        });
    }
}

4.编写画廊页面

a.编写画廊页面

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFC0CB"
    android:clipChildren="false">

    <com.wuhenzhizao.titlebar.widget.CommonTitleBar
        android:id="@+id/title"
        style="@style/StyleTitle"
        app:centerText="@string/gallery_title"
        app:showBottomLine="true" />

    <com.example.viewpagegallery.MyViewPager
        android:id="@+id/viewPager"
        android:layout_width="240dp"
        android:layout_height="400dp"
        android:layout_centerInParent="true"
        android:clipChildren="false" />

    <TextView
        tools:text="1/4"
        android:id="@+id/tv_num_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="30dp"
        android:textColor="#909090"
        android:textSize="18sp" />
</RelativeLayout>

b.编写Activity

public class GalleryActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener { 
   

    @BindView(R.id.viewPager)
    MyViewPager viewPager;
    @BindView(R.id.tv_num_title)
    TextView tvNumTitle;
    @BindView(R.id.title)
    CommonTitleBar mTitle;
    private GalleryAdapter mGalleryAdapter;
    private List<PhotoVo> mPhotoList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) { 
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gallery);
        ButterKnife.bind(this);
        initViews();
    }

    @SuppressLint("DefaultLocale")
    private void initViews() { 
   
        mTitle.setListener((v, action, extra) -> { 
   
            switch (action) { 
   
                case CommonTitleBar.ACTION_LEFT_BUTTON:
                    finish();
                    break;
                case CommonTitleBar.ACTION_RIGHT_TEXT:
                    break;
            }
        });
        mPhotoList = (List<PhotoVo>) getIntent().getSerializableExtra("photoList");
        mGalleryAdapter = new GalleryAdapter(mPhotoList, this);
        tvNumTitle.setText(String.format("%d/%d", 1, mPhotoList.size()));
        viewPager.setAdapter(mGalleryAdapter);
        viewPager.addOnPageChangeListener(this);
        viewPager.setPageTransformer(true, new RotationPageTransForm());
        viewPager.setOffscreenPageLimit(2); //下面会说到
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
   

    }

    @Override
    public void onPageSelected(int position) { 
   
        // 每当页数发生改变时重新设定一遍当前的页数和总页数
        tvNumTitle.setText((position + 1) + "/" + mPhotoList.size());
    }

    @Override
    public void onPageScrollStateChanged(int state) { 
   

    }
}

c.画廊适配器

public class GalleryAdapter extends PagerAdapter { 
   
    private List<PhotoVo> mPhotos;
    private Context mContext;

    public GalleryAdapter(List<PhotoVo> mPhotos, Context mContext) { 
   
        this.mPhotos = mPhotos;
        this.mContext = mContext;
    }

    @Override
    public int getCount() { 
   
        return mPhotos.size();
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { 
   
        return view == object;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) { 
   
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_gallery, container, false);
        PhotoView photoView = view.findViewById(R.id.photo_view);
        Glide.with(mContext).load(mPhotos.get(position).getFile().getPath())
                .into(photoView);
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { 
   
        container.removeView((View) object);
    }
}

5.新增拖拽效果,高度模仿微信朋友圈

a.增加拖拽处理类RecycleItemTouchHelper

public class RecycleItemTouchHelper extends ItemTouchHelper.Callback { 
   
    private static final String TAG = "RecycleItemTouchHelper";
    private final ItemTouchHelperCallback helperCallback;

    public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) { 
   
        this.helperCallback = helperCallback;
    }

    /** * 设置滑动类型标记 * * @param recyclerView * @param viewHolder * @return 返回一个整数类型的标识,用于判断Item那种移动行为是允许的 */
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
   
        Log.e(TAG, "getMovementFlags: ");
        int drafFlags = 0;
        int swipeFlags;
        //START 右向左 END左向右 LEFT 向左 RIGHT向右 UP向上
        //如果某个值传0,表示不触发该操作,次数设置支持上下拖拽,支持向右滑动
        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { 
   
            drafFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            swipeFlags = 0;
        }
        return makeMovementFlags(drafFlags, 0);
    }

    /** * Item是否支持长按拖动 * * @return true 支持长按操作 * false 不支持长按操作 */
    @Override
    public boolean isLongPressDragEnabled() { 
   
        return super.isLongPressDragEnabled();
    }

    /** * Item是否支持滑动 * * @return true 支持滑动操作 * false 不支持滑动操作 */
    @Override
    public boolean isItemViewSwipeEnabled() { 
   
        return super.isItemViewSwipeEnabled();
    }

    /** * 拖拽切换Item的回调 * * @param recyclerView * @param viewHolder * @param target * @return 如果Item切换了位置,返回true;反之,返回false */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 
   
        Log.e(TAG, "onMove: ");
        helperCallback.onMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    /** * 滑动Item * * @param viewHolder * @param direction Item滑动的方向 */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 
   
        Log.e(TAG, "onSwiped: ");
        helperCallback.onItemDelete(viewHolder.getAdapterPosition());
    }

    /** * Item被选中时候回调 * * @param viewHolder * @param actionState 当前Item的状态 * ItemTouchHelper.ACTION_STATE_IDLE 闲置状态 * ItemTouchHelper.ACTION_STATE_SWIPE 滑动中状态 * ItemTouchHelper#ACTION_STATE_DRAG 拖拽中状态 */
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 
   
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { 
   
        super.clearView(recyclerView, viewHolder);
    }

    public interface ItemTouchHelperCallback { 
   
        void onItemDelete(int positon);

        void onMove(int fromPosition, int toPosition);
    }
}

然后在PhotoAdapter实现ItemTouchHelperCallback接口 然后重写接口里面的这两个类达到移动后的item刷新效果

 @Override
    public void onItemDelete(int positon) { 
   
        getData().remove(positon);
        notifyItemRemoved(positon);
    }

    @Override
    public void onMove(int fromPosition, int toPosition) { 
   
        Collections.swap(getData(),fromPosition,toPosition);//交换数据
        notifyItemMoved(fromPosition,toPosition);
    }

b.在MainAcitivity里面绑定itemTouchHelper方法

 ItemTouchHelper.Callback callback = new RecycleItemTouchHelper(mPhotoAdapter);
 ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
 itemTouchHelper.attachToRecyclerView(mRvPhoto);

这样既可实现item的拖拽效果啦

6.源码

创作不易,给博主一键三联,可免费领取博主的爱心代码(详情联系QQ:2872960735)(* ̄︶ ̄) 源码下载地址

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142884.html原文链接:https://javaforall.cn