仿朋友圈相簿圖片選擇以及畫廊效果
阿新 • • 發佈:2021-01-12
仿朋友圈相簿圖片選擇以及畫廊效果
1.效果展示
該demo適配Android 6、7、10。畫廊效果,支援縮放效果。
視訊展示:
(等我B站視訊稽核通過再來修改)
部分截圖:
文章有點長,如果沒時間就拉到最底下下載原始碼,再給個一鍵三聯哈(* ̄︶ ̄)
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.原始碼
創作不易,給博主一鍵三聯,可免費領取博主的愛心程式碼(詳情聯絡QQ:2872960735)(* ̄︶ ̄)
原始碼下載地址