zoukankan      html  css  js  c++  java
  • PhotoPickerNewDemo【PhotoPicker0.9.12的个性化修改以及使用(内部glide版本号是4.1.1)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处!

    前言

    本Demo使用的是PhotoPicker 0.9.12版本,里面集成的glide版本号是4.1.1。这里就不进行特殊的个性化处理了(比如新增NewImagePagerDialogFragment.java用于对话框样式预览图片、新增NewPhotoPickerFragment.java用于单独作为自定义DialogFragment的其中一个Fragment和其他Fragment共存),而是记录下使用步骤(当然了,github上讲解的很清楚了,大家可以直接参考《donglua/PhotoPicker》)。

    不过,本文对PhotoPicker进行了简单的修改,对UI进行了部分修改。【所以本Demo最后使用的是方式2——通过引入PhotoPicker这个module的方式】

    效果图

      

    代码分析

    引入PhotoPicker有两种方式【二选一】

    1、通过Gradle方式,在APP的build.gradle中引用【见导入步骤

    2、下载整个压缩包,然后导入PhotoPicker的module,然后修改图片资源

    2.1、下载压缩包

    2.2、导入PhotoPicker的Module

    提示下面的错误:

    2.3、解决Plugin with id 'com.novoda.bintray-release' not found.问题

    在项目的build.gradle文件中添加以下代码

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
    buildscript {
        
        repositories {
            google()
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:3.0.1'
            //解决PhotoPicker的Plugin with id 'com.novoda.bintray-release' not found.
            classpath 'com.novoda:bintray-release:0.5.0'
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }

     2.4、修改图片资源(比如__picker_ic_photo_black_48dp.png、__picker_checkbox_marked.png、__picker_checkbox_n.png)

    注意:需要修改所有drawable-xxxx目录下的图片

    原始的图片资源:

    修改后的图片资源:

    2.5、添加图片资源【__picker_transparent_bg.png、down_arrow.png、up_arrow.png】

    添加到drawable-xxhdpi目录下

    2.6、修改drawable目录下的__picker_photo_bg.xml和__picker_checkbox_bg.xml【主要用于替换图片列表项的底部背景图】

    原代码1:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
      <item android:state_selected="true">
        <shape>
          <stroke android:color="@color/__picker_item_photo_border_selected"
              android:width="1dip"/>
        </shape>
      </item>
    
      <item>
        <shape>
          <stroke android:color="@color/__picker_item_photo_border_n"
              android:width="1dip"/>
        </shape>
      </item>
    
    
    </selector>
    __picker_photo_bg.xml

    修改后的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:state_selected="true">
        <shape android:shape="rectangle">
          <stroke android:width="2dip"
                  android:color="@color/__picker_item_photo_border_selected"/>
          <solid android:color="@color/__picker_selected_bg"/>
          <solid></solid>
        </shape>
      </item>
    
      <item android:drawable="@drawable/__picker_transparent_bg">
        <shape android:shape="rectangle">
          <stroke android:width="2dip"
                  android:color="@color/__picker_item_photo_border_n"/>
          <!--<solid android:color="#00000000"/>-->
        </shape>
      </item>
    </selector>

    原代码2:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
      <item android:state_selected="true">
        <layer-list>
          <item>
            <shape>
              <corners android:radius="2dip"/>
              <padding android:top="-2dip"
                  android:left="-2dip"
                  android:bottom="-2dip"
                  android:right="-2dip"/>
              <stroke android:width="1dip"
                  android:color="@android:color/white"/>
            </shape>
          </item>
          <item android:drawable="@drawable/__picker_checkbox_marked"/>
        </layer-list>
      </item>
    
      <item>
        <layer-list>
          <item>
            <shape>
              <corners android:radius="2dip"/>
              <padding android:top="-2dip"
                  android:left="-2dip"
                  android:bottom="-2dip"
                  android:right="-2dip"/>
              <stroke android:width="1dip"
                  android:color="@android:color/white"/>
            </shape>
          </item>
          <item android:drawable="@drawable/__picker_checkbox_n"/>
        </layer-list>
      </item>
    
    </selector>
    __picker_checkbox_bg.xml

    修改后的

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
      <item android:state_selected="true">
        <layer-list>
          <!--<item>
            <shape>
              <corners android:radius="10dip"/>
              <padding android:top="-2dip"
                  android:left="-2dip"
                  android:bottom="-2dip"
                  android:right="-2dip"/>
              <stroke android:width="1dip"
                  android:color="@android:color/white"/>
              <solid android:color="@android:color/white"></solid>
            </shape>
          </item>-->
          <item android:drawable="@drawable/__picker_checkbox_marked"/>
        </layer-list>
      </item>
    
      <item>
        <layer-list>
          <!--<item>
            <shape>
              <corners android:radius="10dip"/>
              <padding android:top="-2dip"
                  android:left="-2dip"
                  android:bottom="-2dip"
                  android:right="-2dip"/>
              <stroke android:width="1dip"
                  android:color="@android:color/white"/>
              <solid android:color="@android:color/white"></solid>
            </shape>
          </item>-->
          <item android:drawable="@drawable/__picker_checkbox_n"/>
        </layer-list>
      </item>
    
    </selector>

    2.7、修改__picker_fragment_photo_picker.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.support.v7.widget.RecyclerView
          android:id="@+id/rv_photos"
          android:layout_width="match_parent"
          android:gravity="center"
          android:layout_weight="1"
          android:layout_height="0dip"
          />
    
    
      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:background="?attr/colorPrimary"
          >
            <Button
                android:id="@+id/button"
                android:text="@string/__picker_all_image"
                android:layout_width="wrap_content"
                android:gravity="center"
                android:layout_height="wrap_content"
                style="@style/Widget.AppCompat.ActionButton"
                />
    
      </LinearLayout>
    
    </LinearLayout>
    __picker_fragment_photo_picker.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.support.v7.widget.RecyclerView
            android:id="@+id/rv_photos"
            android:layout_width="match_parent"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_height="0dip"
            />
    
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#e9e9e9"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            >
            <!--<Button
                android:id="@+id/button"
                android:text="@string/__picker_all_image"
                android:layout_width="wrap_content"
                android:gravity="center"
                android:layout_height="wrap_content"
                style="@style/Widget.AppCompat.ActionButton"
                />-->
    
            <TextView
                android:id="@+id/button"
                android:layout_width="0.0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:text="@string/__picker_all_image"
                android:textColor="@color/__picker_text_120"
                android:textSize="16sp"
                android:drawableRight="@drawable/up_arrow"
                android:drawablePadding="8dp"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:gravity="center_vertical"
                style="@style/Widget.AppCompat.ActionButton"
                />
            <!-- 现在用不到,只是占位用 -->
            <ImageView
                android:layout_width="0.0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:src="@drawable/__picker_camera"
                android:layout_gravity="center_vertical"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                android:visibility="invisible"/>
    
        </LinearLayout>
    
    </LinearLayout>

    2.8、修改PhotoPickerFragment.java文件【主要是实现上下箭头的更换功能】

    搜索why,查看改动的代码:

    package me.iwf.photopicker.fragment;
    
    import android.content.ActivityNotFoundException;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.widget.DefaultItemAnimator;
    import android.support.v7.widget.ListPopupWindow;
    import android.support.v7.widget.OrientationHelper;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.PopupWindow;
    import android.widget.TextView;
    
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.RequestManager;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import me.iwf.photopicker.PhotoPickerActivity;
    import me.iwf.photopicker.R;
    import me.iwf.photopicker.adapter.PhotoGridAdapter;
    import me.iwf.photopicker.adapter.PopupDirectoryListAdapter;
    import me.iwf.photopicker.entity.Photo;
    import me.iwf.photopicker.entity.PhotoDirectory;
    import me.iwf.photopicker.event.OnPhotoClickListener;
    import me.iwf.photopicker.utils.AndroidLifecycleUtils;
    import me.iwf.photopicker.utils.ImageCaptureManager;
    import me.iwf.photopicker.utils.MediaStoreHelper;
    import me.iwf.photopicker.utils.PermissionsConstant;
    import me.iwf.photopicker.utils.PermissionsUtils;
    
    import static android.app.Activity.RESULT_OK;
    import static me.iwf.photopicker.PhotoPicker.DEFAULT_COLUMN_NUMBER;
    import static me.iwf.photopicker.PhotoPicker.EXTRA_PREVIEW_ENABLED;
    import static me.iwf.photopicker.PhotoPicker.EXTRA_SHOW_GIF;
    import static me.iwf.photopicker.utils.MediaStoreHelper.INDEX_ALL_PHOTOS;
    
    /**
     * Created by donglua on 15/5/31.
     */
    public class PhotoPickerFragment extends Fragment {
    
      private ImageCaptureManager captureManager;
      private PhotoGridAdapter photoGridAdapter;
    
      private PopupDirectoryListAdapter listAdapter;
      //所有photos的路径
      private List<PhotoDirectory> directories;
      //传入的已选照片
      private ArrayList<String> originalPhotos;
    
      private int SCROLL_THRESHOLD = 30;
      int column;
      //目录弹出框的一次最多显示的目录数目
      public static int COUNT_MAX = 4;
      private final static String EXTRA_CAMERA = "camera";
      private final static String EXTRA_COLUMN = "column";
      private final static String EXTRA_COUNT = "count";
      private final static String EXTRA_GIF = "gif";
      private final static String EXTRA_ORIGIN = "origin";
      private ListPopupWindow listPopupWindow;
      private RequestManager mGlideRequestManager;
    
      public static PhotoPickerFragment newInstance(boolean showCamera, boolean showGif,
          boolean previewEnable, int column, int maxCount, ArrayList<String> originalPhotos) {
        Bundle args = new Bundle();
        args.putBoolean(EXTRA_CAMERA, showCamera);
        args.putBoolean(EXTRA_GIF, showGif);
        args.putBoolean(EXTRA_PREVIEW_ENABLED, previewEnable);
        args.putInt(EXTRA_COLUMN, column);
        args.putInt(EXTRA_COUNT, maxCount);
        args.putStringArrayList(EXTRA_ORIGIN, originalPhotos);
        PhotoPickerFragment fragment = new PhotoPickerFragment();
        fragment.setArguments(args);
        return fragment;
      }
    
      @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setRetainInstance(true);
    
        mGlideRequestManager = Glide.with(this);
    
        directories = new ArrayList<>();
        originalPhotos = getArguments().getStringArrayList(EXTRA_ORIGIN);
    
        column = getArguments().getInt(EXTRA_COLUMN, DEFAULT_COLUMN_NUMBER);
        boolean showCamera = getArguments().getBoolean(EXTRA_CAMERA, true);
        boolean previewEnable = getArguments().getBoolean(EXTRA_PREVIEW_ENABLED, true);
    
        photoGridAdapter = new PhotoGridAdapter(getActivity(), mGlideRequestManager, directories, originalPhotos, column);
        photoGridAdapter.setShowCamera(showCamera);
        photoGridAdapter.setPreviewEnable(previewEnable);
    
        listAdapter  = new PopupDirectoryListAdapter(mGlideRequestManager, directories);
    
        Bundle mediaStoreArgs = new Bundle();
    
        boolean showGif = getArguments().getBoolean(EXTRA_GIF);
        mediaStoreArgs.putBoolean(EXTRA_SHOW_GIF, showGif);
        MediaStoreHelper.getPhotoDirs(getActivity(), mediaStoreArgs,
            new MediaStoreHelper.PhotosResultCallback() {
              @Override public void onResultCallback(List<PhotoDirectory> dirs) {
                directories.clear();
                directories.addAll(dirs);
                photoGridAdapter.notifyDataSetChanged();
                listAdapter.notifyDataSetChanged();
                adjustHeight();
              }
            });
    
        captureManager = new ImageCaptureManager(getActivity());
      }
    
      @Override
      public void onResume() {
        super.onResume();
        if(getActivity() instanceof PhotoPickerActivity){
          PhotoPickerActivity photoPickerActivity = (PhotoPickerActivity) getActivity();
          photoPickerActivity.updateTitleDoneItem();
        }
      }
    
    
      @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
          Bundle savedInstanceState) {
    
        final View rootView = inflater.inflate(R.layout.__picker_fragment_photo_picker, container, false);
    
        RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.rv_photos);
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(column, OrientationHelper.VERTICAL);
        layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(photoGridAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
    
        //final Button btSwitchDirectory = (Button) rootView.findViewById(R.id.button);
        final TextView btSwitchDirectory = (TextView) rootView.findViewById(R.id.button);//why
    
        listPopupWindow = new ListPopupWindow(getActivity());
        listPopupWindow.setWidth(ListPopupWindow.MATCH_PARENT);
        listPopupWindow.setAnchorView(btSwitchDirectory);
        listPopupWindow.setAdapter(listAdapter);
        listPopupWindow.setModal(true);
        listPopupWindow.setDropDownGravity(Gravity.BOTTOM);
    
        listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listPopupWindow.dismiss();
    
            PhotoDirectory directory = directories.get(position);
    
            btSwitchDirectory.setText(directory.getName());
    
            photoGridAdapter.setCurrentDirectoryIndex(position);
            photoGridAdapter.notifyDataSetChanged();
          }
        });
    
        //添加popwindow隐藏的监听--why
        listPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
          @Override
          public void onDismiss() {
            //监听popwindow隐藏的时候的操作
            Drawable drawableUp = ContextCompat.getDrawable(getActivity(),R.drawable.up_arrow);
            drawableUp.setBounds(0, 0, drawableUp.getMinimumWidth(), drawableUp.getMinimumHeight());
            btSwitchDirectory.setCompoundDrawables(null,null,drawableUp,null);
          }
        });
    
        photoGridAdapter.setOnPhotoClickListener(new OnPhotoClickListener() {
          @Override public void onClick(View v, int position, boolean showCamera) {
            final int index = showCamera ? position - 1 : position;
    
            List<String> photos = photoGridAdapter.getCurrentPhotoPaths();
    
            ImagePagerFragment imagePagerFragment =
                ImagePagerFragment.newInstance(photos, index);
    
            ((PhotoPickerActivity) getActivity()).addImagePagerFragment(imagePagerFragment);
          }
        });
    
        photoGridAdapter.setOnCameraClickListener(new OnClickListener() {
          @Override public void onClick(View view) {
            if (!PermissionsUtils.checkCameraPermission(PhotoPickerFragment.this)) return;
            if (!PermissionsUtils.checkWriteStoragePermission(PhotoPickerFragment.this)) return;
            openCamera();
          }
        });
    
        btSwitchDirectory.setOnClickListener(new OnClickListener() {
          @Override public void onClick(View v) {
    
            if (listPopupWindow.isShowing()) {
              listPopupWindow.dismiss();
            } else if (!getActivity().isFinishing()) {
              adjustHeight();
              //why
              Drawable drawableDown = ContextCompat.getDrawable(getActivity(),R.drawable.down_arrow);
              drawableDown.setBounds(0, 0, drawableDown.getMinimumWidth(), drawableDown.getMinimumHeight());
              btSwitchDirectory.setCompoundDrawables(null,null,drawableDown,null);
              listPopupWindow.show();
            }
          }
        });
    
    
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
          @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            // Log.d(">>> Picker >>>", "dy = " + dy);
            if (Math.abs(dy) > SCROLL_THRESHOLD) {
              mGlideRequestManager.pauseRequests();
            } else {
              resumeRequestsIfNotDestroyed();
            }
          }
          @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
              resumeRequestsIfNotDestroyed();
            }
          }
        });
    
        return rootView;
      }
    
      private void openCamera() {
        try {
          Intent intent = captureManager.dispatchTakePictureIntent();
          startActivityForResult(intent, ImageCaptureManager.REQUEST_TAKE_PHOTO);
        } catch (IOException e) {
          e.printStackTrace();
        } catch (ActivityNotFoundException e) {
          Log.e("PhotoPickerFragment", "No Activity Found to handle Intent", e);
        }
      }
    
      @Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ImageCaptureManager.REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
    
          if (captureManager == null) {
            FragmentActivity activity = getActivity();
            captureManager = new ImageCaptureManager(activity);
          }
    
          captureManager.galleryAddPic();
          if (directories.size() > 0) {
            String path = captureManager.getCurrentPhotoPath();
            PhotoDirectory directory = directories.get(INDEX_ALL_PHOTOS);
            directory.getPhotos().add(INDEX_ALL_PHOTOS, new Photo(path.hashCode(), path));
            directory.setCoverPath(path);
            photoGridAdapter.notifyDataSetChanged();
          }
        }
      }
    
      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
          switch (requestCode) {
            case PermissionsConstant.REQUEST_CAMERA:
            case PermissionsConstant.REQUEST_EXTERNAL_WRITE:
              if (PermissionsUtils.checkWriteStoragePermission(this) &&
                      PermissionsUtils.checkCameraPermission(this)) {
                openCamera();
              }
              break;
          }
        }
      }
    
      public PhotoGridAdapter getPhotoGridAdapter() {
        return photoGridAdapter;
      }
    
    
      @Override public void onSaveInstanceState(Bundle outState) {
        captureManager.onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
      }
    
    
      @Override public void onViewStateRestored(Bundle savedInstanceState) {
        captureManager.onRestoreInstanceState(savedInstanceState);
        super.onViewStateRestored(savedInstanceState);
      }
    
      public ArrayList<String> getSelectedPhotoPaths() {
        return photoGridAdapter.getSelectedPhotoPaths();
      }
    
      public void adjustHeight() {
        if (listAdapter == null) return;
        int count = listAdapter.getCount();
        count = count < COUNT_MAX ? count : COUNT_MAX;
        if (listPopupWindow != null) {
          listPopupWindow.setHeight(count * getResources().getDimensionPixelOffset(R.dimen.__picker_item_directory_height));
        }
      }
    
      @Override public void onDestroy() {
        super.onDestroy();
    
        if (directories == null) {
          return;
        }
    
        for (PhotoDirectory directory : directories) {
          directory.getPhotoPaths().clear();
          directory.getPhotos().clear();
          directory.setPhotos(null);
        }
        directories.clear();
        directories = null;
      }
    
      private void resumeRequestsIfNotDestroyed() {
        if (!AndroidLifecycleUtils.canLoadImage(this)) {
          return;
        }
    
        mGlideRequestManager.resumeRequests();
      }
    }
    PhotoPickerFragment.java

    2.9、修改__picker_item_photo.xml,设置图片列表项的内边距值

    <?xml version="1.0" encoding="utf-8"?>
    <me.iwf.photopicker.widget.SquareItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="3dp"
        >
      <ImageView
          android:padding="1dip"
          android:layout_gravity="center"
          android:id="@+id/iv_photo"
          android:scaleType="centerCrop"
          android:layout_width="match_parent"
          android:background="@drawable/__picker_photo_bg"
          android:layout_height="match_parent"
          android:adjustViewBounds="true"
          />
    
      <ImageView
          android:layout_alignParentTop="true"
          android:layout_alignParentRight="true"
          android:clickable="true"
          android:paddingTop="10dip"
          android:paddingRight="10dip"
          android:paddingLeft="20dip"
          android:paddingBottom="20dip"
          android:id="@+id/v_selected"
          android:src="@drawable/__picker_checkbox_bg"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          />
    
    </me.iwf.photopicker.widget.SquareItemLayout>

    2.10、修改图片列表项选中后的颜色值(colors.xml文件中修改)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
      <color name="__picker_pager_bg">#CA000000</color>
      <color name="__picker_selected_bg">#44000000</color>
      <color name="__picker_black_40">#282828</color>
      <color name="__picker_common_primary">#f3f3f3</color>
    
      <color name="__picker_text_40">#282828</color>
      <color name="__picker_text_80">#505050</color>
      <color name="__picker_text_120">#787878</color>
      <!--<color name="__picker_item_photo_border_selected">#ff99cc00</color>-->
      <!--why-->
      <color name="__picker_item_photo_border_selected">#1A78EC</color>
      <color name="__picker_item_photo_border_n">#33ffffff</color>
    
    </resources>

    至此,PhotoPicker基本上修改完了,后续可以根据需求继续修改。下面就是运用到APP中的步骤【导入步骤跟方式1几乎一样,不同的就是app的build.gradle导入的photopicker不一样】。

    2.11、在APP的build.gradle文件添加以下代码

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.why.project.photopickernewdemo"
            minSdkVersion 16
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    
        //PhotoPicker
        //compile 'me.iwf.photopicker:PhotoPicker:0.9.12@aar'
        //方式2:使用自己导入并且修改后的module
        implementation project(':PhotoPicker')
        //compile 'com.android.support:appcompat-v7:27.1.1'//需要注释,因为新建项目都会自动引用这个appcompat-v7
        compile 'com.android.support:recyclerview-v7:27.1.1'
        compile 'com.android.support:design:27.1.1'
        compile 'com.github.bumptech.glide:glide:4.1.1'
    }

    2.12、在APP的AndroidManifest.xml中添加以下代码

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.photopickernewdemo">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
    
            <!-- PhotoPicker -->
            <activity android:name="me.iwf.photopicker.PhotoPickerActivity"
                      android:theme="@style/customTheme"
                />
            <activity android:name="me.iwf.photopicker.PhotoPagerActivity"
                      android:theme="@style/customTheme"/>
        </application>
    
    </manifest>

    2.13、在styles.xml文件中添加以下代码

    <resources>
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>
    
    
        <!-- PhotoPicker -->
        <style name="customTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- 解开注释的话,右侧的完成文本始终是设置的颜色,无法实现禁用状态下是灰色的功能 -->
            <!--<item name="actionBarTheme">@style/actionBarTheme</item>-->
            <!--背景颜色值-->
            <item name="colorPrimary">#ffffff</item>
            <!--导航栏高度值-->
            <item name="actionBarSize">52dp</item>
            <!-- 状态栏着色 -->
            <item name="colorPrimaryDark">#378dfc</item>
        </style>
        <style name="actionBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
            <!--标题颜色值-->
            <item name="android:textColorPrimary">#434343</item>
            <!--右侧完成文本的大小值-->
            <item name="android:textSize">16sp</item>
            <!--右侧完成文本的颜色值-->
            <item name="android:actionMenuTextColor">#1A78EC</item>
        </style>
    
    </resources>

     具体使用参考《三、使用方法》

    使用步骤

    一、项目组织结构图

    注意事项:

    1、  导入类文件后需要change包名以及重新import R文件路径

    2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

    二、导入步骤【方式1的导入步骤】

    (1)在app的build.gradle文件中导入PhotoPicker【修改recyclerview、design的版本号和appcompat-v7统一】

    注意:appcompat-v7version >= 23.0.0

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.why.project.photopickernewdemo"
            minSdkVersion 16
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    
        //PhotoPicker
        compile 'me.iwf.photopicker:PhotoPicker:0.9.12@aar'
        //compile 'com.android.support:appcompat-v7:27.1.1'//需要注释,因为新建项目都会自动引用这个appcompat-v7
        compile 'com.android.support:recyclerview-v7:27.1.1'
        compile 'com.android.support:design:27.1.1'
        compile 'com.github.bumptech.glide:glide:4.1.1'
    }

    (2)在APP的styles.xml文件中自定义样式(颜色、高度值等)

    <resources>
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>
    
    
        <!-- PhotoPicker -->
        <style name="customTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- 解开注释的话,右侧的完成文本始终是设置的颜色,无法实现禁用状态下是灰色的功能 -->
            <!--<item name="actionBarTheme">@style/actionBarTheme</item>-->
            <!--背景颜色值-->
            <item name="colorPrimary">#ffffff</item>
            <!--导航栏高度值-->
            <item name="actionBarSize">52dp</item>
            <!-- 状态栏着色 -->
            <item name="colorPrimaryDark">#378dfc</item>
        </style>
        <style name="actionBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
            <!--标题颜色值-->
            <item name="android:textColorPrimary">#434343</item>
            <!--右侧完成文本的大小值-->
            <item name="android:textSize">16sp</item>
            <!--右侧完成文本的颜色值-->
            <item name="android:actionMenuTextColor">#1A78EC</item>
        </style>
    
    </resources>

    (3)在APP的AndroidManifest.xml中添加以下代码【注意:使用上面自定义的样式

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.photopickernewdemo">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
    
            <!-- PhotoPicker -->
            <activity android:name="me.iwf.photopicker.PhotoPickerActivity"
                      android:theme="@style/customTheme"
                />
            <activity android:name="me.iwf.photopicker.PhotoPagerActivity"
                      android:theme="@style/customTheme"/>
        </application>
    
    </manifest>

    三、使用方法

    (1)在项目中实现Recyclerview基本数据展现【比较简单,省略】【或者参考《Android快速开发常用知识点系列目录》下的RecyclerView篇章相关文章】

     注意:PictureAdapter.java中使用的Glide是4.1.1版本,所以写法跟之前的Glide3.7.0版本是不一样的。

    package com.why.project.photopickernewdemo.adapter;
    
    import android.content.Context;
    import android.net.Uri;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.Priority;
    import com.bumptech.glide.load.engine.DiskCacheStrategy;
    import com.bumptech.glide.request.RequestOptions;
    import com.why.project.photopickernewdemo.R;
    import com.why.project.photopickernewdemo.bean.PictureBean;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
    
    /**
     * Created by HaiyuKing
     * Used 照片网格适配器
     */
    
    public class PictureAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    
        private static final String TAG = PictureAdapter.class.getSimpleName();
    
        /**上下文*/
        private Context myContext;
        /**自定义列表项标题集合*/
        private ArrayList<PictureBean> listitemList;
    
        final static int TYPE_ADD = 1;
        final static int TYPE_PHOTO = 2;
    
        public final static int MAX = 15;//总数目,这里根据实际情况设置,设置100基本上表明无限制了
    
        /*
        * 构造函数
        */
        public PictureAdapter(Context context, ArrayList<PictureBean> itemlist) {
            myContext = context;
            listitemList = itemlist;
        }
    
        /**
         * 获取总的条目数
         */
        @Override
        public int getItemCount() {
            Log.w(TAG,"{getItemCount}listitemList.size()="+listitemList.size());
            int count = listitemList.size();
            if (count > MAX) {
                count = MAX;
            }
            count = count + 1;
            return count;
        }
    
        @Override
        public int getItemViewType(int position) {
            Log.w(TAG,"{getItemViewType}position="+position);
            Log.w(TAG,"{getItemViewType}listitemList.size()="+listitemList.size());
            return (position == listitemList.size()) ? TYPE_ADD : TYPE_PHOTO;
        }
    
        /**
         * 创建ViewHolder
         */
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if(viewType == TYPE_ADD) {
                View viewfoot = LayoutInflater.from(myContext).inflate(R.layout.pic_grid_foot_item, parent, false);
                ItemFootViewHolder itemfootViewHolder = new ItemFootViewHolder(viewfoot);
                return itemfootViewHolder;
            } else if(viewType == TYPE_PHOTO) {
                View view = LayoutInflater.from(myContext).inflate(R.layout.pic_grid_item, parent, false);
                ItemViewHolder itemViewHolder = new ItemViewHolder(view);
                return itemViewHolder;
            }
            return null;
        }
    
        /**
         * 声明列表项ViewHolder*/
        static class ItemViewHolder extends RecyclerView.ViewHolder
        {
            public ItemViewHolder(View view)
            {
                super(view);
                griditemLayout = (LinearLayout) view.findViewById(R.id.griditemLayout);
                griditemimgLayout = (RelativeLayout) view.findViewById(R.id.griditemimgLayout);
                grid_img = (ImageView) view.findViewById(R.id.grid_img);
                grid_img_state = (TextView) view.findViewById(R.id.grid_img_state);
            }
    
            LinearLayout griditemLayout;
            RelativeLayout griditemimgLayout;
            ImageView grid_img;
    
            TextView grid_img_state;
        }
    
        /**
         * 声明最后一个ViewHolder*/
        static class ItemFootViewHolder extends RecyclerView.ViewHolder
        {
            public ItemFootViewHolder(View view)
            {
                super(view);
                gridfootitemLayout = (RelativeLayout) view.findViewById(R.id.gridfootitemLayout);
            }
            RelativeLayout gridfootitemLayout;
        }
    
        /**
         * 将数据绑定至ViewHolder
         */
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int index) {
    
            if(viewHolder instanceof ItemViewHolder){
                PictureBean listItemModel = listitemList.get(index);
                final ItemViewHolder itemViewHold = ((ItemViewHolder)viewHolder);
    
                Uri uri = Uri.fromFile(new File(listItemModel.getPicPath()));
    
                RequestOptions options = new RequestOptions()
                        //设置等待时的图片
                        .placeholder(R.drawable.img_loading)
                        //设置加载失败后的图片显示
                        .error(R.drawable.img_error)
                        //缓存策略,跳过内存缓存【此处应该设置为false,否则列表刷新时会闪一下】
                        .skipMemoryCache(false)
                        //缓存策略,硬盘缓存-仅仅缓存最终的图像,即降低分辨率后的(或者是转换后的)
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        //设置图片加载的优先级
                        .priority(Priority.HIGH);
    
                Glide.with(myContext)
                        .load(uri)
                        .apply(options)
                        //默认淡入淡出动画
                        .transition(withCrossFade())
                        .into(itemViewHold.grid_img);
    
                itemViewHold.grid_img_state.setText("(" + (index+1) + "/" + listitemList.size() + ")");
    
                //如果设置了回调,则设置点击事件
                if (mOnItemClickLitener != null)
                {
                    itemViewHold.grid_img.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            int position = itemViewHold.getLayoutPosition();//在增加数据或者减少数据时候,position和index就不一样了
                            mOnItemClickLitener.onItemClick(view,position);
                        }
                    });
                }
            }else if(viewHolder instanceof ItemFootViewHolder){
                final ItemFootViewHolder itemFootViewHold = ((ItemFootViewHolder)viewHolder);
                //如果设置了回调,则设置点击事件
                if (mOnItemClickLitener != null)
                {
                    itemFootViewHold.gridfootitemLayout.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            mOnItemClickLitener.onItemAddClick();
                        }
                    });
                }
            }
    
        }
    
        /**
         * 添加Item--用于动画的展现*/
        public void addItem(int position,PictureBean itemModel) {
            listitemList.add(position,itemModel);
            notifyItemInserted(position);
        }
        /**
         * 删除Item--用于动画的展现*/
        public void removeItem(int position) {
            listitemList.remove(position);
            notifyItemRemoved(position);
        }
    
        /*=====================添加OnItemClickListener回调================================*/
        public interface OnItemClickLitener
        {
            /**图片的点击事件*/
            void onItemClick(View view, int position);
            /**添加的点击事件*/
            void onItemAddClick();
        }
    
        private OnItemClickLitener mOnItemClickLitener;
    
        public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
        {
            this.mOnItemClickLitener = mOnItemClickLitener;
        }
    
        //返回当前图片集合的所有路径集合【用于预览】
        public List<String> getAllPhotoPaths() {
            List<String> allPhotoPaths = new ArrayList<String>(listitemList.size());
            for (PictureBean  pictureBean: listitemList) {
                allPhotoPaths.add(pictureBean.getPicPath());
            }
            return allPhotoPaths;
        }
    
    }

    (2)常规使用

    package com.why.project.photopickernewdemo;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.widget.Toast;
    
    import com.why.project.photopickernewdemo.adapter.PictureAdapter;
    import com.why.project.photopickernewdemo.bean.PictureBean;
    import com.why.project.photopickernewdemo.utils.Globals;
    
    import java.util.ArrayList;
    
    import me.iwf.photopicker.PhotoPicker;
    import me.iwf.photopicker.PhotoPreview;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = MainActivity.class.getSimpleName();
    
        private RecyclerView mRecyclerView;
        private ArrayList<PictureBean> mPictureBeansList;
        private PictureAdapter mPictureAdapter;
    
        private ArrayList<String> selPhotosPath = null;//选中的图片路径集合
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initViews();
            initDatas();
            initEvents();
        }
    
        private void initViews() {
            mRecyclerView = findViewById(R.id.picture_grid);
        }
    
        private void initDatas() {
            selPhotosPath = new ArrayList<String>();
            //=============图片九宫格=========================
            mPictureAdapter = null;
            mPictureBeansList = new ArrayList<PictureBean>();
            //设置布局管理器
            GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
            mRecyclerView.setLayoutManager(gridLayoutManager);
    
            if(mPictureAdapter == null){
                //设置适配器
                mPictureAdapter = new PictureAdapter(this, mPictureBeansList);
                mRecyclerView.setAdapter(mPictureAdapter);
                //添加分割线
                //设置添加删除动画
                //调用ListView的setSelected(!ListView.isSelected())方法,这样就能及时刷新布局
                mRecyclerView.setSelected(true);
            }else{
                mPictureAdapter.notifyDataSetChanged();
            }
        }
    
        private void initEvents() {
            //图片九宫格点击事件
            mPictureAdapter.setOnItemClickLitener(new PictureAdapter.OnItemClickLitener() {
                @Override
                public void onItemClick(View v, int position) {
                    //打开图片预览界面
                    ArrayList<String> photos = (ArrayList<String>) mPictureAdapter.getAllPhotoPaths();
                    PhotoPreview.builder()
                            .setPhotos(photos)
                            .setCurrentItem(position)
                            .setShowDeleteButton(false)
                            .start(MainActivity.this);
                }
    
                @Override
                public void onItemAddClick() {
                    PhotoPicker.builder()
                            .setPhotoCount(mPictureAdapter.MAX)
                            .setGridColumnCount(3)
                            //.setSelected(selPhotosPath)
                            .start(MainActivity.this, Globals.CHOOSE_PIC_REQUEST_CODE);
                }
            });
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            Log.w(TAG, "{onActivityResult}resultCode="+resultCode);
            Log.w(TAG, "{onActivityResult}requestCode="+requestCode);
            if (resultCode == Activity.RESULT_OK) {
                //选择照片
                if(requestCode == Globals.CHOOSE_PIC_REQUEST_CODE){
    
                    if (data != null) {
                        selPhotosPath = data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
                    }
                    if (selPhotosPath != null) {
    
                        //下面的代码主要用于这样一个场景,就是注释了.setSelected(selPhotosPath)之后,还想要保证选择的图片不重复
                        /*for(String path : selPhotosPath){
                            Log.w(TAG,"path="+path);///storage/emulated/0/tempHxzk/IMG_1498034535796.jpg
                            boolean existThisPic = false;
                            for(int i=0;i<mPictureBeansList.size();i++){
                                if(path.equals(mPictureBeansList.get(i).getPicPath())){
                                    //如果新选择的图片集合中存在之前选中的图片,那么跳过去
                                    existThisPic = true;
                                    break;
                                }
                            }
                            if(! existThisPic){
                                PictureBean pictureBean = new PictureBean();
                                pictureBean.setPicPath(path);
                                pictureBean.setPicName(getFileName(path));
                                //去掉总数目的限制,这里通过增大MAX的数字来实现
                                if (mPictureBeansList.size() < mPictureAdapter.MAX) {
                                    mPictureBeansList.add(pictureBean);
                                } else {
                                    Toast.makeText(MainActivity.this, "最多可以选择" + mPictureAdapter.MAX + "张图片", Toast.LENGTH_SHORT).show();
                                    break;
                                }
                            }
                        }*/
    
                        //是常规操作,和上面的代码不可共存
                        for (String path : selPhotosPath) {
                            PictureBean pictureBean = new PictureBean();
                            pictureBean.setPicPath(path);
                            pictureBean.setPicName(Globals.getFileName(path));
                            //去掉总数目的限制,这里通过增大MAX的数字来实现
                            if (mPictureBeansList.size() < mPictureAdapter.MAX) {
                                mPictureBeansList.add(pictureBean);
                            } else {
                                Toast.makeText(MainActivity.this, "最多可以选择" + mPictureAdapter.MAX + "张图片", Toast.LENGTH_SHORT).show();
                                break;
                            }
                        }
                        mPictureAdapter.notifyDataSetChanged();
                    }
                }
            }
        }
    }

    混淆配置

    # PhotoPicker混淆
    # Glide
    -keep public class * implements com.bumptech.glide.module.GlideModule
    -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
        **[] $VALUES;
        public *;
    }
    # support-v7-appcompat
    -keep public class android.support.v7.widget.** { *; }
    -keep public class android.support.v7.internal.widget.** { *; }
    -keep public class android.support.v7.internal.view.menu.** { *; }
    -keep public class * extends android.support.v4.view.ActionProvider {
        public <init>(android.content.Context);
    }
    # support-design
    -dontwarn android.support.design.**
    -keep class android.support.design.** { *; }
    -keep interface android.support.design.** { *; }
    -keep public class android.support.design.R$* { *; }

    参考资料

    donglua/PhotoPicker

    项目demo下载地址

    https://github.com/haiyuKing/PhotoPickerNewDemo

  • 相关阅读:
    CS 165 notes
    使用GDB和Valgrind调试C程序
    vi编辑器的学习使用(十四)
    vi编辑器的学习使用(十三)
    vi编辑器的学习使用(十)
    vi编辑器的学习使用(十九)
    vi编辑器的学习使用(十八)
    vi编辑器的学习使用(十一)
    vi编辑器的学习使用(十七)
    vi编辑器的学习使用(十五)
  • 原文地址:https://www.cnblogs.com/whycxb/p/9382293.html
Copyright © 2011-2022 走看看