SoFunction
Updated on 2025-04-05

Android WeChat picture browsing framework design

1. Business scenarios

1. Send pictures in the chat interface ==>Multiple selection + "Send" in the upper right corner + picture preview ==>Picture preview supports "Send" logic in the upper right corner
2. Post a dynamic ==>Multiple selection + "Complete" in the upper right corner + Picture preview ==>Image preview supports "Complete" logic in the upper right corner
3. Change profile avatar ==>Single-choice click + Image preview screenshot ==>Image preview screenshot supports the "Use" logic in the upper right corner

2. Intent parameter design;(Intent parameter transfer principle: try not to use custom type dedicated parameters)

1. The most basic parameter transfer (the maximum number of optional pictures, title in the upper right corner, single-select mode or multiple-select mode, and parameters that return the result)

  /** Maximum number of image selections, int type, default 9 */
  public static final String EXTRA_SELECT_COUNT = "max_select_count";

  /** Title of send button If completed or sent */
  public static final String EXTRA_SUBMIT_TITLE = "extra_submit_title";

  /** Picture selection mode, default multiple selection */
  public static final String EXTRA_SELECT_MODE = "select_count_mode";

  /** Select the result and return to the ArrayList<String> picture path collection */
  public static final String EXTRA_RESULT = "select_result";

2. Extended partial parameter transmission (whether the first Item of the picture selection interface displays the photo function, and whether the preview activity supports the "check and cancel end" check button)

 /** Whether to display the camera, the default display */
  public static final String EXTRA_SHOW_CAMERA = "show_camera";

  /** Whether to jump to ImageDetailCheckPicsAct*/
  public static final String EXTRA_JUMPTOCHECKPICS = "is_jumpto_checkpics";

3. After selecting 5 pictures in "Post Dynamic Selection", go to select pictures – the image browser needs to set the selected picture check status to check

 /** By default, selected set */
  public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list";

4. Screenshot function (in single-select mode, if screenshot mode is activated, then select and jump to the screenshot interface)

  /** Whether to return the original image or jump to the screenshot first and then return */
  public static final String RESIZEBIT = "RESIZEBIT";
  /** The path saved by screenshot */
  public static final String RESULT = "resultPath";
  /** Single choice Whether to take a screenshot */
  public static final String MODE_SCALE_BOOLEAN = "MODE_SCALE_BOOLEAN";
  /** Single choice The width of the blue box in the screenshot area; unit dp */
  public static final String SCALEW = "scaleW";
  /** Single choice The height of the blue box in the screenshot area; unit dp */
  public static final String SCALEH = "SCALEH";
  /** Single choice The pixel width of the image saved after screenshot; unit sp */
  public static final String LIMITW = "limitWidth";
  /** Single choice The pixels saved by the image after screenshot are high; unit sp */
  public static final String LIMITH = "limitHight";
  /** Save path of the single-select screenshot */
  public static final String MODE_SCALE_PATH = "MODE_SCALE_PATH";

3. After clarifying the requirements, design

omitted here; the shared code implementation functions have not been designed to optimize the code readability is poor
Code project github addressIMAlbum

4. Code usage method

 public static void jumpToSelectPics(Activity mContext, boolean isShowCamera, int selectMaxCount, int selectMode,
      String submitBtnStr, boolean isJumpToCheckPics, ArrayList&lt;String&gt; hasSelectList) {
    Intent intent = new Intent(mContext, );

    // whether show camera
    (MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, isShowCamera);

    // String of submit button
    (MultiImageSelectorActivity.EXTRA_SUBMIT_TITLE, submitBtnStr);

    // String of submit button
    (MultiImageSelectorFragment.EXTRA_JUMPTOCHECKPICS, isJumpToCheckPics);

    // max select image amount
    (MultiImageSelectorActivity.EXTRA_SELECT_COUNT, selectMaxCount);

    // select mode (MultiImageSelectorActivity.MODE_SINGLE OR MultiImageSelectorActivity.MODE_MULTI)
    (MultiImageSelectorActivity.EXTRA_SELECT_MODE, selectMode);

    // EXTRA_DEFAULT_SELECTED_LIST

    if (hasSelectList != null) {
      (MultiImageSelectorActivity.EXTRA_DEFAULT_SELECTED_LIST, hasSelectList);
    }
    //
    (intent, REQUEST_IMAGE);
  }


  /**
    * Image format jpeg
    * @param picResultPath The address to be saved for the image
    * @param scaleW Width of screenshot area Unit dp
    * @param scaleH The height of the screenshot area Unit dp
    * @param limtWidth The width of the cropped figure
    * @param limitHight The height of the cropped image
    * @param isScaleImg Whether to zoom in and out according to the ratio of limtWidth and limitHight
    * @description:
    * @author zhangjianlin (990996641)
    * @date June 11, 2015 at 4:25:00 pm
    */
  public static void jumpToSelecAndCropImg(Activity mContext, String picResultPath, int scaleW, int scaleH,
      int limtWidth, int limitHight, boolean isScaleImg) {
    Intent intent = new Intent(mContext, );

    // whether show camera
    (MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, false);

    // max select image amount
    (MultiImageSelectorActivity.EXTRA_SELECT_COUNT, 1);
    // select mode (MultiImageSelectorActivity.MODE_SINGLE OR MultiImageSelectorActivity.MODE_MULTI)
    (MultiImageSelectorActivity.EXTRA_SELECT_MODE, MultiImageSelectorActivity.MODE_SINGLE);
    // (MultiImageSelectorActivity.EXTRA_DEFAULT_CROP_CAMERA, isScaleImg);

    (, isScaleImg);
    (, picResultPath);
    (, scaleW);
    (, scaleH);
    (, limtWidth);
    (, limitHight);

    (intent, REQUEST_CROPIMAGE);
  }

  /**
    * @Description: Select a single image without cutting
    * Return value ArrayList
    switch (requestCode) {
    case IntentUtils.REQUEST_IMAGE:
         if (data != null) {
           ArrayList<String> resultList = data
               .getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
         }
         break;
    }
    * @param mContext
    */
  public static void jumpToSelectNoCropImg(Activity mContext) {
    jumpToSelectPics(mContext, false, 2, MultiImageSelectorActivity.MODE_SINGLE);
  }

5. Baseselectactivity class

  /**
   @Override
   public void onConfigurationChanged(Configuration newConfig) {
     (newConfig);
   }
  <activity android:name=""
       android:launchMode="singleTask"
       android:configChanges="orientation|keyboardHidden|screenSize"
       >
     </activity>



  * @Description: Select the act of the image
  * @author zhangjianlin
  * @date 2015-9-24 2:06:28 pm
  */
public abstract class BaseSelectPicAct extends Activity {

  private final int CROPCAMARA_TAKEPHOTO = 1003;
  private final int CROPCAMARA_SELECTFROMALBUM = 1004;

  /** Select from Photos */
  private final int ACTIVITY_RESULT_CROPCAMARA_WITH_DATA = 1;
  private File mPicFile; // Select the image path  private String picPath;


  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    (newConfig);
  }


  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    (requestCode, resultCode, data);
    if (resultCode != RESULT_OK) { return; }
    switch (requestCode) {
      case IntentUtils.REQUEST_IMAGE: // Select a photo        /** add by zjl */
        if (null != data) {
          ArrayList&lt;String&gt; resultList = data
              .getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
          hasSelectPicsNoCrop(resultList);
          /* if (null != resultList) {
           * 
           * } */
        }
        break;

      case ACTIVITY_RESULT_CROPCAMARA_WITH_DATA: // Photograph        /* if (()) {
         * 
         * } */
        if (mPicFile == null &amp;&amp; !(picPath)) mPicFile = new File(picPath);
        if (null != mPicFile &amp;&amp; ()) {
          hasTakePhotoPic(mPicFile);
        }
        break;
      case IntentUtils.REQUEST_CROPIMAGE:
        if (null == data) { return; }
        if ((()) || !()) {
          (this, "No picture selected", Toast.LENGTH_LONG).show();
          return;
        }
        String mPicNativePath = ().getAbsolutePath() +"/image" + ();
        try {
          ((), mPicNativePath);
        } catch (Exception e) {
          ();
        }

        hasPicsCroped(mPicNativePath);
        break;
    }
  };

  protected void selectPhoto() {
    (this);
  }

  protected void selectPhotoAndCrop() {
    mPicFile = ();
    /* photoIntent = ((mPicFile)); startActivityForResult(photoIntent, Constant.ACTIVITY_RESULT_CROPIMAGE_WITH_DATA); */
    (this, (), 300, 300, 600, 600, true);
  }

  /** Photograph */
  protected void takePhoto() {
    if (!()) {
      (this, "No memory card", Toast.LENGTH_LONG).show();
      return;
    }
    mPicFile = new File(().getAbsolutePath() + "/"
        + () + ".jpg");
    picPath = ();
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    (MediaStore.EXTRA_OUTPUT, (mPicFile));
    startActivityForResult(intent, ACTIVITY_RESULT_CROPCAMARA_WITH_DATA);
  }

  protected abstract void hasSelectPicsNoCrop(ArrayList&lt;String&gt; resultList);

  protected abstract void hasTakePhotoPic(File mPicFile);

  protected abstract void hasPicsCroped(String mPicNativePath);

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    ("picPathCache", picPath);
    (outState);
  }

  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    picPath = ("picPathCache");
    (savedInstanceState);
  }
}

6. Select simple gallery

public class AlbumTestAct extends BaseSelectPicAct implements OnClickListener {

  private ImageView iv_showresult;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    (savedInstanceState);
    setContentView(.act_albumtest);
    findViewById(.tv_takephoto).setOnClickListener(this);
    findViewById(.tv_selectphoto).setOnClickListener(this);
    findViewById(.tv_selectandcrop).setOnClickListener(this);
    iv_showresult = (ImageView) findViewById(.iv_showresult);

  }

  @Override
  public void onClick(View v) {
    // TODO Auto-generated method stub
    switch (()) {
    case .tv_takephoto:
      takePhoto();
      break;
    case .tv_selectphoto:
      selectPhoto();
      break;
    case .tv_selectandcrop:
      selectPhotoAndCrop();
      break;

    default:
      break;
    }
  }

  @Override
  protected void hasSelectPicsNoCrop(ArrayList<String> resultList) {
    // TODO Auto-generated method stub
    if (null != resultList) {
      if(() > 0)
      {
        ().displayImage(((0)), iv_showresult);
      }
    }
  }

  @Override
  protected void hasTakePhotoPic(File mPicFile) {
    // TODO Auto-generated method stub
    if(null != mPicFile && ())
    {
    ().displayImage((()), iv_showresult);
    }
  }

  @Override
  protected void hasPicsCroped(String mPicNativePath) {
    // TODO Auto-generated method stub
    if(null != mPicNativePath && new File(mPicNativePath).exists())
    {
    ().displayImage((mPicNativePath), iv_showresult);
    }
  }

}


The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.