Android高仿微信图片选择上传工具
Posted datou_SleepyzzZ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android高仿微信图片选择上传工具相关的知识,希望对你有一定的参考价值。
源码托管地址:https://github.com/SleepyzzZ/photo-selector
话不多说,先上效果图(高仿微信图片选择器):
图片选择界面:
图片预览界面:
批量上传图片:
实现的功能介绍:
1、图片异步加载,使用Glide开源库实现加载;
2、图片的预览界面,支持左右滑动,双击放大浏览;
3、图片批量上传,使用OkHttp来实现与Servlet服务器的通信;
使用方法(android Studio):
新建工程,File->New->Import Module导入photo-selector,记得在你的build.gradle引入Module及注册Activity;
直接在你的主Activity调用以下方法(代码托管中已经给出调用demo):
/**
*暴露接口
* @param context
* @param maxSelectCount-限制的最大图片选择数量
* @param searchPath-指定图片搜索路径(若为null-表示搜索所有图片)
* @param url-服务器地址
*/
public static void actionStart(Context context, int maxSelectCount, String searchPath, String url)
Intent intent = new Intent(context, PhotoPickerActivity.class);
intent.putExtra(PhotoPickerFragment.EXTRA_SELECT_COUNT, maxSelectCount);
intent.putExtra(PhotoPickerFragment.EXTRA_DEFAULT_SELECTED_LIST, searchPath);
intent.putExtra(HTTP_URL, url);
context.startActivity(intent);
下面贴出关键部分代码:
图片选择和预览界面利用fragment实现,其中选择界面用GridView控件,每个Item包含加载的图片、选择标记和掩膜mask,通过回调实现图片和标记的点击事件。
其中,点击图片进入文件夹内所有图片预览界面,点击选择标记选择图片并掩膜展示图片选择后效果。
图片预览界面fragment、adapter
package com.sleepyzzz.photo_selector.fragment;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.GridView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.sleepyzzz.photo_selector.R;
import com.sleepyzzz.photo_selector.activity.PhotoPickerActivity;
import com.sleepyzzz.photo_selector.adapter.PhotoPickerAdapter;
import com.sleepyzzz.photo_selector.entity.ImageFolder;
import com.sleepyzzz.photo_selector.event.OnItemClickListerner;
import com.sleepyzzz.photo_selector.event.OnPhotoDirSelected;
import com.sleepyzzz.photo_selector.view.ListImageDirPopupWindow;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* User: datou_SleepyzzZ(SleepyzzZ19911002@126.com)
* Date: 2016-04-14
* Time: 15:24
* FIXME
*/
public class PhotoPickerFragment extends Fragment
private final static String TAG = PhotoPickerFragment.class.getSimpleName();
/**
* 最大图片选择数量
*/
public static final String EXTRA_SELECT_COUNT = "max_select_count";
/**
* 默认选择集
*/
public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list";
/**
* 屏幕高度
*/
public static final String EXTRA_SCREEN_HEIGHT = "screen_height";
/**
* 控件
*/
private GridView mGridView;
private Button mPreviewBtn;
private Button mPopWindowBtn;
private RelativeLayout mBottonLy;
private Button mCommitBtn;
private TextView mTopTv;
/**
* 当前选择的图片文件夹
*/
private File mImgDir;
/**
* 第一个扫描到的文件夹
*/
private String firstDirName;
/**
* 当前文件夹下图片名列表
*/
private List<String> mImgNames;
/**
* 临时辅助类,用于防止同一个文件夹的多次扫描
*/
private HashSet<String> mDirPaths = new HashSet<String>();
/**
* 扫描拿到所有的图片文件夹
*/
private List<ImageFolder> mImageFolders = new ArrayList<ImageFolder>();
/**
* 文件夹选择popupwindow
*/
private ListImageDirPopupWindow mDirPopupWindow;
/**
* 文件选择适配器
*/
private PhotoPickerAdapter mPickerAdapter;
private ProgressDialog mProgressDialog;
private int mDesireSelectCount;
private int mScreenHeight;
private String mDesireSearchPath;
private View rootView;
public static PhotoPickerFragment newInstance(int screenHeight, int selectCount, String searchPath)
Bundle args = new Bundle();
args.putInt(EXTRA_SCREEN_HEIGHT, screenHeight);
args.putInt(EXTRA_SELECT_COUNT, selectCount);
args.putString(EXTRA_DEFAULT_SELECTED_LIST, searchPath);
PhotoPickerFragment fragment = new PhotoPickerFragment();
fragment.setArguments(args);
return fragment;
private Handler mHandler = new Handler()
@Override
public void handleMessage(Message msg)
mProgressDialog.dismiss();
//为View绑定数据
data2View();
//初始化展示文件夹的PopupWindow
initListDirPopupWindow();
;
private void initListDirPopupWindow()
mDirPopupWindow = new ListImageDirPopupWindow(ViewGroup.LayoutParams.MATCH_PARENT,
(int) (0.7 * mScreenHeight), mImageFolders, LayoutInflater.from(getActivity())
.inflate(R.layout.list_folder, null));
mDirPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener()
@Override
public void onDismiss()
//设置背景颜色变暗
WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();
lp.alpha = 1.0f;
getActivity().getWindow().setAttributes(lp);
);
//设置选择文件夹的回调
mDirPopupWindow.setOnPhotoDirSelected(new OnPhotoDirSelected()
@Override
public void onSelected(ImageFolder folder)
mImgDir = new File(folder.getDir());
mImgNames = Arrays.asList(mImgDir.list(new FilenameFilter()
@Override
public boolean accept(File dir, String filename)
if(filename.endsWith(".jpg") || filename.endsWith(".png")
|| filename.endsWith(".jpeg"))
return true;
return false;
));
mPickerAdapter = new PhotoPickerAdapter(getActivity(), mImgNames,
R.layout.grid_item_image, mImgDir.getAbsolutePath(), mDesireSelectCount);
mGridView.setAdapter(mPickerAdapter);
//item回调
mPickerAdapter.setOnItemClickListerner(new OnItemClickListerner()
@Override
public void onPhotoClick(View view, int position)
List<String> mImgUrls = new ArrayList<String>();
for (int i = 0;i < mImgNames.size(); i++)
mImgUrls.add(mImgDir + "/" + mImgNames.get(i));
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
PhotoPagerFragment fragment =
PhotoPagerFragment.newInstance(mImgUrls, position, mDesireSelectCount, screenLocation,
view.getWidth(), view.getHeight());
((PhotoPickerActivity) getActivity()).addPhotoPagerFragment(fragment);
@Override
public void onMarkClick(String path)
refreshUI(path);
);
mPopWindowBtn.setText(folder.getName());
mDirPopupWindow.dismiss();
);
private void refreshUI(String path)
if(PhotoPickerAdapter.mSelectedImage.contains(path))
if(PhotoPickerAdapter.mSelectedImage.size() != 0)
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText(getResources().getString(R.string.preview)
+ "(" + PhotoPickerAdapter.mSelectedImage.size() + ")");
mCommitBtn.setEnabled(true);
mCommitBtn.setText(String.format("%s(%d/%d)", getString(R.string.action_done)
, PhotoPickerAdapter.mSelectedImage.size(), mDesireSelectCount));
else
mPreviewBtn.setEnabled(false);
mPreviewBtn.setText(R.string.preview);
mCommitBtn.setEnabled(false);
mCommitBtn.setText(R.string.action_done);
else
if(PhotoPickerAdapter.mSelectedImage.size() == 0)
mPreviewBtn.setEnabled(false);
mPreviewBtn.setText(R.string.preview);
mCommitBtn.setEnabled(false);
mCommitBtn.setText(R.string.action_done);
else
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText(getResources().getString(R.string.preview)
+ "(" + PhotoPickerAdapter.mSelectedImage.size() + ")");
mCommitBtn.setEnabled(true);
mCommitBtn.setText(String.format("%s(%d/%d)",
getString(R.string.action_done), PhotoPickerAdapter.mSelectedImage.size(), mDesireSelectCount));
/**
* 绑定数据
*/
private void data2View()
if(mImgDir == null)
Toast.makeText(getActivity(), "no scanned images",
Toast.LENGTH_SHORT).show();
return;
mPopWindowBtn.setText(firstDirName);
mImgNames = Arrays.asList(mImgDir.list());
/**
* 文件夹路径个图片路径分开保存,减少了内存的消耗
*/
mPickerAdapter = new PhotoPickerAdapter(getActivity(), mImgNames,
R.layout.grid_item_image, mImgDir.getAbsolutePath(), mDesireSelectCount);
mGridView.setAdapter(mPickerAdapter);
//item选择回调
mPickerAdapter.setOnItemClickListerner(new OnItemClickListerner()
@Override
public void onPhotoClick(View view, int position)
List<String> mImgUrls = new ArrayList<String>();
for (int i = 0;i < mImgNames.size(); i++)
mImgUrls.add(mImgDir + "/" + mImgNames.get(i));
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
PhotoPagerFragment fragment =
PhotoPagerFragment.newInstance(mImgUrls, position, mDesireSelectCount, screenLocation,
view.getWidth(), view.getHeight());
((PhotoPickerActivity) getActivity()).addPhotoPagerFragment(fragment);
@Override
public void onMarkClick(String path)
refreshUI(path);
);
@Override
public void onAttach(Context context)
super.onAttach(context);
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
//选择图片数量
mDesireSelectCount = getArguments().getInt(EXTRA_SELECT_COUNT);
//屏幕高度
mScreenHeight = getArguments().getInt(EXTRA_SCREEN_HEIGHT);
//默认选择
mDesireSearchPath = getArguments().getString(EXTRA_DEFAULT_SELECTED_LIST);
//扫描图片
getImages();
private void initView(View view)
mGridView = (GridView) view.findViewById(R.id.gd_image);
mPopWindowBtn = (Button) view.findViewById(R.id.btn_choose_dir);
mPreviewBtn = (Button) view.findViewById(R.id.btn_preview);
mBottonLy = (RelativeLayout) view.findViewById(R.id.layout_bottom_actionbar);
mCommitBtn = (Button) getActivity().findViewById(R.id.btn_commit);
mTopTv = (TextView) getActivity().findViewById(R.id.tv_back);
mTopTv.setText(R.string.images);
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
//保存fragment视图状态
rootView = getPersistentView(inflater, container, savedInstanceState, R.layout.fragment_grid_image);
initView(rootView);
initEvent();
return rootView;
/**
* 保存fragment视图状态
* @param inflater
* @param container
* @param savedInstanceState
* @param layoutId
* @return
*/
private View getPersistentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layoutId)
if(rootView == null)
rootView = inflater.inflate(layoutId, container, false);
else
ViewGroup parent = (ViewGroup) rootView.getParent();
if(parent != null)
parent.removeView(rootView);
return rootView;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
private void initEvent()
mPopWindowBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
mDirPopupWindow.setAnimationStyle(R.style.anim_popup_dir);
mDirPopupWindow.showAsDropDown(mBottonLy, 0, 0);
//设置背景颜色变暗
WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();
lp.alpha = .3f;
getActivity().getWindow().setAttributes(lp);
);
//初始化按钮
if(PhotoPickerAdapter.mSelectedImage == null ||
PhotoPickerAdapter.mSelectedImage.size() <= 0)
mPreviewBtn.setText(R.string.preview);
mPreviewBtn.setEnabled(false);
mCommitBtn.setText(R.string.action_done);
mCommitBtn.setEnabled(false);
else
mPreviewBtn.setText(getResources().getString(R.string.preview)
+ "(" + PhotoPickerAdapter.mSelectedImage.size() + ")");
mPreviewBtn.setEnabled(true);
mCommitBtn.setText(String.format("%s(%d/%d)", getString(R.string.action_done),
PhotoPickerAdapter.mSelectedImage.size(), mDesireSelectCount));
mCommitBtn.setEnabled(true);
//监听预览按钮
mPreviewBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
int[] screenLocation = new int[2];
v.getLocationOnScreen(screenLocation);
PhotoPagerFragment fragment =
PhotoPagerFragment.newInstance(PhotoPickerAdapter.mSelectedImage, 0, mDesireSelectCount, screenLocation,
v.getWidth(), v.getHeight());
((PhotoPickerActivity) getActivity()).addPhotoPagerFragment(fragment);
);
private String[] IMAGE_PROJECTION =
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media._ID
;
/**
* 扫描图片
*/
private void getImages()
if(!Environment.getExternalStorageState().
equals(Environment.MEDIA_MOUNTED))
Toast.makeText(getActivity(), "no external storage", Toast.LENGTH_SHORT).show();
return;
//显示进度条
mProgressDialog = ProgressDialog.show(getActivity(), null, "loading...");
new Thread(new Runnable()
@Override
public void run()
String firstImage = null;
Uri mImgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = getActivity().getContentResolver();
Cursor mCursor = null;
//只查询jpeg和png图片
if (mDesireSearchPath == null)
mCursor = mContentResolver.query(mImgUri, IMAGE_PROJECTION,
IMAGE_PROJECTION[3] + "=? or "
+ IMAGE_PROJECTION[3] + "=?",
new String[]"image/jpeg", "image/png",
IMAGE_PROJECTION[2] + " DESC");
else
mCursor = mContentResolver.query(mImgUri, IMAGE_PROJECTION,
IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[0]
+ " like '%" + mDesireSearchPath + "%'", null,
IMAGE_PROJECTION[2] + " DESC");
while(mCursor.moveToNext())
//获得图片路径
String path = mCursor.getString(mCursor.
getColumnIndex(MediaStore.Images.Media.DATA));
//拿到第一张图片的路径
if(firstImage == null)
firstImage = path;
//获取该图片的父路径名
File parentFile = new File(path).getParentFile();
if(parentFile == null)
continue;
String dirPath = parentFile.getAbsolutePath();
ImageFolder imageFolder = null;
//利用一个HashSet防止多次扫描同一个文件夹
if(mDirPaths.contains(dirPath))
continue;
else
mDirPaths.add(dirPath);
//初始化ImageLoader
imageFolder = new ImageFolder();
imageFolder.setDir(dirPath);
imageFolder.setFirstImagePath(path);
//获取优先显示的图片父路径名
if(mCursor.getPosition() == 0)
mImgDir = parentFile;
firstDirName = imageFolder.getName();
int picSize = parentFile.list(new FilenameFilter()
@Override
public boolean accept(File dir, String filename)
if(filename.endsWith(".jpg")
|| filename.endsWith(".png")
|| filename.endsWith("jpeg"))
return true;
return false;
).length;
//需要显示所有图片,修改此处
imageFolder.setCount(picSize);
mImageFolders.add(imageFolder);
mCursor.close();
//扫描完成,辅助的HashSet释放内存
mDirPaths = null;
mHandler.sendEmptyMessage(0x110);
).start();
public PhotoPickerAdapter getPhotoPickerAdapter()
return mPickerAdapter;
package com.sleepyzzz.photo_selector.adapter;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.sleepyzzz.photo_selector.R;
import com.sleepyzzz.photo_selector.event.OnItemClickListerner;
import com.sleepyzzz.photo_selector.util.ViewHolder;
import com.sleepyzzz.photo_selector.view.SquaredImageView;
import java.util.LinkedList;
import java.util.List;
/**
* User: datou_SleepyzzZ(SleepyzzZ19911002@126.com)
* Date: 2016-04-11
* Time: 13:22
* FIXME
*/
public class PhotoPickerAdapter extends CommonAdapter<String>
private static final String TAG = PhotoPickerAdapter.class.getSimpleName();
/**
* 用户选择的图片,存储为图片的完整路径
*/
public static List<String> mSelectedImage = new LinkedList<String>();
/**
* 文件夹路径
*/
private String mDirPath;
/**
* 选择图片数量限制
*/
private int mSelectCount;
/**
* 回调接口方法
*/
private OnItemClickListerner mOnItemClickListerner = null;
public PhotoPickerAdapter(Context context, List<String> mDatas, int itemLayoutId,
String dirPath, int selectCount)
super(context, mDatas, itemLayoutId);
this.mDirPath = dirPath;
this.mSelectCount = selectCount;
@Override
public void convert(final ViewHolder helper, final String item)
//设置图片
helper.setImageResource(R.id.siv_image, R.drawable.default_error);
helper.setImageResource(R.id.iv_checkmark, R.drawable.btn_unselected);
helper.setImageByUrl(R.id.siv_image, mDirPath + "/" + item);
final SquaredImageView mImageView = helper.getView(R.id.siv_image);
final ImageView mCheckMark = helper.getView(R.id.iv_checkmark);
final View mask = helper.getView(R.id.mask);
mask.setVisibility(View.GONE);
//设置Mark的点击事件
mCheckMark.setOnClickListener(new View.OnClickListener()
//选择,则将图片变暗,反之则反之
@Override
public void onClick(View v)
//已经选择过该图片
if (mSelectedImage.contains(mDirPath + "/" + item))
mSelectedImage.remove(mDirPath + "/" + item);
mOnItemClickListerner.onMarkClick(mDirPath + "/" +item); //回调
mCheckMark.setImageResource(R.drawable.btn_unselected);
mask.setVisibility(View.GONE);
else
//未选择该图片
if (mSelectedImage.size() == mSelectCount)
Toast.makeText(mContext, R.string.msg_amount_limit,
Toast.LENGTH_SHORT).show();
return;
mSelectedImage.add(mDirPath + "/" + item);
mOnItemClickListerner.onMarkClick(mDirPath + "/" +item); //回调
mCheckMark.setImageResource(R.drawable.btn_selected);
mask.setVisibility(View.VISIBLE);
);
//已经选择过的图片,显示出选择效果
if (mSelectedImage.contains(mDirPath + "/" + item))
mCheckMark.setImageResource(R.drawable.btn_selected);
mask.setVisibility(View.VISIBLE);
//设置photo的点击事件
mImageView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
mOnItemClickListerner.onPhotoClick(v, helper.getPosition());
);
/**
* 回调方法
* @param onItemClickListerner
*/
public void setOnItemClickListerner(OnItemClickListerner onItemClickListerner)
this.mOnItemClickListerner = onItemClickListerner;
public List<String> getmSelectedImage()
return mSelectedImage;
@Override
public void setSelectIndex(int i)
@Override
public int getSetlectIndex()
return 0;
图片预览界面可以通过右下角选择按钮,添加或删除图片选择项
图片预览界面fragmenty、adapter
package com.sleepyzzz.photo_selector.fragment;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.nineoldandroids.view.ViewPropertyAnimator;
import com.sleepyzzz.photo_selector.R;
import com.sleepyzzz.photo_selector.adapter.PhotoPagerAdapter;
import com.sleepyzzz.photo_selector.adapter.PhotoPickerAdapter;
import com.sleepyzzz.photo_selector.event.OnPagerCLickListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* User: datou_SleepyzzZ(SleepyzzZ19911002@126.com)
* Date: 2016-04-15
* Time: 20:47
* FIXME
*/
public class PhotoPagerFragment extends Fragment
public final static String ARG_PATH = "PATHS";
public final static String ARG_POSITION = "CURRENT_POSITION";
public final static String ARG_MAXCOUNT = "MAX_SELECT_COUNT";
private ArrayList<String> mPaths;
private ViewPager mViewPager;
private PhotoPagerAdapter mPagerAdapter;
private RelativeLayout mBottombar;
private ImageView mSelectMark;
private Button mSelectBtn;
private Button mCommitBtn;
private TextView mToptv;
private boolean isShowBottomBar = true;
public final static long ANIM_DURATION = 200L;
public final static String ARG_THUMBNAIL_TOP = "THUMBNAIL_TOP";
public final static String ARG_THUMBNAIL_LEFT = "THUMBNAIL_LEFT";
public final static String ARG_THUMBNAIL_WIDTH = "THUMBNAIL_WIDTH";
public final static String ARG_THUMBNAIL_HEIGHT = "THUMBNAIL_HEIGHT";
public final static String ARG_HAS_ANIM = "HAS_ANIM";
private int thumbnailTop = 0;
private int thumbnailLeft = 0;
private int thumbnailWidth = 0;
private int thumbnailHeight = 0;
private boolean hasAnim = false;
private final ColorMatrix colorizerMatrix = new ColorMatrix();
private int currentPosition = 0;
private int mDesireSelectCount;
public static PhotoPagerFragment newInstance(List<String> paths, int position, int maxSelectCount)
PhotoPagerFragment fragment = new PhotoPagerFragment();
Bundle args = new Bundle();
args.putStringArray(ARG_PATH, paths.toArray(new String[paths.size()]));
args.putInt(ARG_POSITION, position);
args.putBoolean(ARG_HAS_ANIM, false);
args.putInt(ARG_MAXCOUNT, maxSelectCount);
fragment.setArguments(args);
return fragment;
public static PhotoPagerFragment newInstance(List<String> paths, int position, int maxSelectCount, int[] screenLocation, int thumbnailWidth, int thumbnailHeight)
PhotoPagerFragment fragment = newInstance(paths, position, maxSelectCount);
fragment.getArguments().putInt(ARG_THUMBNAIL_LEFT, screenLocation[0]);
fragment.getArguments().putInt(ARG_THUMBNAIL_TOP, screenLocation[1]);
fragment.getArguments().putInt(ARG_THUMBNAIL_WIDTH, thumbnailWidth);
fragment.getArguments().putInt(ARG_THUMBNAIL_HEIGHT, thumbnailHeight);
fragment.getArguments().putBoolean(ARG_HAS_ANIM, true);
return fragment;
public void setPhotos(List<String> paths, int position)
this.mPaths.clear();
this.mPaths.addAll(paths);
this.currentPosition = position;
mViewPager.setCurrentItem(position);
mViewPager.getAdapter().notifyDataSetChanged();
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
mPaths = new ArrayList<>();
Bundle bundle = getArguments();
if (bundle != null)
String[] pathArr = bundle.getStringArray(ARG_PATH);
mPaths.clear();
if (pathArr != null)
mPaths = new ArrayList<>(Arrays.asList(pathArr));
hasAnim = bundle.getBoolean(ARG_HAS_ANIM);
currentPosition = bundle.getInt(ARG_POSITION);
mDesireSelectCount = bundle.getInt(ARG_MAXCOUNT);
thumbnailTop = bundle.getInt(ARG_THUMBNAIL_TOP);
thumbnailLeft = bundle.getInt(ARG_THUMBNAIL_LEFT);
thumbnailWidth = bundle.getInt(ARG_THUMBNAIL_WIDTH);
thumbnailHeight = bundle.getInt(ARG_THUMBNAIL_HEIGHT);
mPagerAdapter = new PhotoPagerAdapter(getActivity(), mPaths);
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_photo_pager, container, false);
mViewPager = (ViewPager) rootView.findViewById(R.id.vp_photos);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(currentPosition);
mViewPager.setOffscreenPageLimit(5);
mBottombar = (RelativeLayout) rootView.findViewById(R.id.ly_bottom_bar);
mSelectMark = (ImageView) rootView.findViewById(R.id.iv_select_box);
mSelectBtn = (Button) rootView.findViewById(R.id.btn_selectbox);
mCommitBtn = (Button) getActivity().findViewById(R.id.btn_commit);
mToptv = (TextView) getActivity().findViewById(R.id.tv_back);
//更新第一张预览图片的selectbox
if (PhotoPickerAdapter.mSelectedImage.contains(
mPaths.get(currentPosition)))
mSelectMark.setImageResource(R.drawable.selectbox_marked);
//进入pager显示Top TextView(eg:2/19)
mToptv.setText(String.format("%d/%d", currentPosition+1,
mPaths.size()));
if (savedInstanceState == null && hasAnim)
ViewTreeObserver observer = mViewPager.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
@Override
public boolean onPreDraw()
mViewPager.getViewTreeObserver().removeOnPreDrawListener(this);
int[] screenLocation = new int[2];
mViewPager.getLocationOnScreen(screenLocation);
thumbnailLeft = thumbnailLeft - screenLocation[0];
thumbnailTop = thumbnailTop - screenLocation[1];
runEnterAnimation();
return true;
);
mPagerAdapter.setOnPagerCLickListener(new OnPagerCLickListener()
@Override
public void onPagerClick()
if(isShowBottomBar)
mBottombar.setVisibility(View.GONE);
isShowBottomBar = !isShowBottomBar;
else
mBottombar.setVisibility(View.VISIBLE);
isShowBottomBar = !isShowBottomBar;
);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
@Override
public void onPageSelected(int position)
hasAnim = currentPosition == position;
if (PhotoPickerAdapter.mSelectedImage.
contains(mPaths.get(position)))
mSelectMark.setImageResource(R.drawable.selectbox_marked);
else
mSelectMark.setImageResource(R.drawable.selectbox_n);
mToptv.setText(String.format("%d/%d", position+1,
mPaths.size()));
@Override
public void onPageScrollStateChanged(int state)
);
mSelectBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
int pos = mViewPager.getCurrentItem();
if (PhotoPickerAdapter.mSelectedImage.
contains(mPaths.get(pos)))
mSelectMark.setImageResource(R.drawable.selectbox_n);
PhotoPickerAdapter.mSelectedImage.remove(mPaths.get(pos));
if (PhotoPickerAdapter.mSelectedImage.size() == 0)
mCommitBtn.setEnabled(false);
mCommitBtn.setText(R.string.action_done);
else
mCommitBtn.setText(String.format("%s(%d/%d)", getString(R.string.action_done)
, PhotoPickerAdapter.mSelectedImage.size(), mDesireSelectCount));
else
if (PhotoPickerAdapter.mSelectedImage.size() < mDesireSelectCount)
mSelectMark.setImageResource(R.drawable.selectbox_marked);
PhotoPickerAdapter.mSelectedImage.add(mPaths.get(pos));
mCommitBtn.setEnabled(true);
mCommitBtn.setText(String.format("%s(%d/%d)", getString(R.string.action_done)
, PhotoPickerAdapter.mSelectedImage.size(), mDesireSelectCount));
else
Toast.makeText(getActivity().getApplicationContext(),
R.string.msg_amount_limit, Toast.LENGTH_SHORT).show();
);
return rootView;
private void runEnterAnimation()
final long duration = ANIM_DURATION;
ViewHelper.setPivotX(mViewPager, 0);
ViewHelper.setPivotY(mViewPager, 0);
ViewHelper.setScaleX(mViewPager, (float) thumbnailWidth / mViewPager.getWidth());
ViewHelper.setScaleY(mViewPager, (float) thumbnailHeight / mViewPager.getHeight());
ViewHelper.setTranslationX(mViewPager, thumbnailLeft);
ViewHelper.setTranslationY(mViewPager, thumbnailTop);
ViewPropertyAnimator.animate(mViewPager)
.setDuration(duration)
.scaleX(1)
.scaleY(1)
.translationX(0)
.translationY(0)
.setInterpolator(new DecelerateInterpolator());
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mViewPager.getBackground(),
"alpha", 0, 255);
bgAnim.setDuration(duration);
bgAnim.start();
ObjectAnimator colorizer = ObjectAnimator.ofFloat(PhotoPagerFragment.this,
"saturation", 0, 1);
colorizer.setDuration(duration);
colorizer.start();
public void runExitAnimation(final Runnable endAction)
if (!getArguments().getBoolean(ARG_HAS_ANIM, false) || !hasAnim)
endAction.run();
return;
final long duration = ANIM_DURATION;
ViewPropertyAnimator.animate(mViewPager)
.setDuration(duration)
.setInterpolator(new AccelerateInterpolator())
.scaleX((float) thumbnailWidth / mViewPager.getWidth())
.scaleY((float) thumbnailHeight / mViewPager.getHeight())
.translationX(thumbnailLeft)
.translationY(thumbnailTop)
.setListener(new Animator.AnimatorListener()
@Override
public void onAnimationStart(Animator animation)
@Override
public void onAnimationEnd(Animator animation)
endAction.run();
@Override
public void onAnimationCancel(Animator animation)
@Override
public void onAnimationRepeat(Animator animation)
);
ObjectAnimator bgAnim =
ObjectAnimator.ofInt(mViewPager.getBackground(), "alpha", 0);
bgAnim.setDuration(duration);
bgAnim.start();
ObjectAnimator colorizer =
ObjectAnimator.ofFloat(PhotoPagerFragment.this, "saturation", 1, 0);
colorizer.setDuration(duration);
colorizer.start();
public void setSaturation(float value)
colorizerMatrix.setSaturation(value);
ColorMatrixColorFilter colorizerFilter = new ColorMatrixColorFilter(colorizerMatrix);
mViewPager.getBackground().setColorFilter(colorizerFilter);
public ViewPager getViewPager()
return mViewPager;
public ArrayList<String> getPaths()
return mPaths;
public int getCurrentPosition()
return mViewPager.getCurrentItem();
package com.sleepyzzz.photo_selector.adapter;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.sleepyzzz.photo_selector.R;
import com.sleepyzzz.photo_selector.event.OnPagerCLickListener;
import java.util.ArrayList;
import java.util.List;
/**
* User: datou_SleepyzzZ(SleepyzzZ19911002@126.com)
* Date: 2016-04-15
* Time: 20:58
* FIXME
*/
public class PhotoPagerAdapter extends PagerAdapter
private List<String> mPaths = new ArrayList<>();
private Context mContext;
private LayoutInflater mInflater;
private OnPagerCLickListener mOnPagerCLickListener;
public void setOnPagerCLickListener(OnPagerCLickListener onPagerCLickListener)
mOnPagerCLickListener = onPagerCLickListener;
public PhotoPagerAdapter(Context context, List<String> paths)
mPaths = paths;
mContext = context;
mInflater = LayoutInflater.from(mContext);
@Override
public Object instantiateItem(ViewGroup container, int position)
View itemView = mInflater.inflate(R.layout.item_pager, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.iv_pager);
//自定义图片异步加载类(大图片存在OOM)
/*ImageLoader.getInstance(3, ImageLoader.Type.LIFO)
.loadImage(mPaths.get(position), imageView);*/
/*Glide.with(mContext)
.load(mPaths.get(position))
.thumbnail(0.1f)
.dontAnimate()
.dontTransform()
.override(800, 800)
.placeholder(R.drawable.ic_photo_black_48dp)
.error(R.drawable.ic_broken_image_black_48dp)
.into(imageView);*/
Glide.with(mContext)
.load(mPaths.get(position))
.thumbnail(0.1f) //先显示.1的缩略图
.dontAnimate()
.dontTransform()
.override(800, 800) //尺寸
.placeholder(R.drawable.ic_photo_black_48dp)
.error(R.drawable.ic_broken_image_black_48dp)
.into(imageView);
imageView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
mOnPagerCLickListener.onPagerClick();
);
/*imageView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
if(mContext instanceof PhotoPickerActivity)
if(!((Activity) mContext).isFinishing())
((Activity) mContext).onBackPressed();
);*/
container.addView(itemView);
return itemView;
@Override
public int getCount()
return mPaths.size();
@Override
public boolean isViewFromObject(View view, Object object)
return view == object;
@Override
public void destroyItem(ViewGroup container, int position, Object object)
container.removeView((View) object);
@Override
public int getItemPosition(Object object)
return POSITION_NONE;
这里也给出了服务器端批量接收图片测试代码:
package com.sleepyzzz.server;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* Servlet implementation class DetectionServlet
*/
@WebServlet("/DetectionServlet")
public class DetectionServlet extends HttpServlet
private static final long serialVersionUID = 1L;
private final static long MAX_FILE_SIZE = 50 * 1024 * 1024;
private final static String[] allowedExt = new String[]
"jpg", "JPG", "JPEG", "jpeg";
private String result;
private DiskFileItemFactory factory;
private ServletFileUpload upload;
private PrintWriter writer;
private ArrayList<FileItem> list;
private String clientIP;
/**
* @see HttpServlet#HttpServlet()
*/
public DetectionServlet()
super();
// TODO Auto-generated constructor stub
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
// TODO Auto-generated method stub
doPost(request, response);
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
this.clientIP = request.getRemoteAddr();
factory = new DiskFileItemFactory();
factory.setSizeThreshold(2*1024*1024); //缓冲区
factory.setRepository(new File(request.getSession() //临时存放文件目录
.getServletContext()
.getRealPath("/")
+ "UploadTemp"));
upload = new ServletFileUpload(factory); //用硬盘文件工厂实例化上传组件
upload.setFileSizeMax(MAX_FILE_SIZE); //最大上传尺寸
writer = response.getWriter();
result = "Upload sucess";
try
list = (ArrayList<FileItem>) upload.parseRequest(request);
catch (FileUploadException e)
// TODO Auto-generated catch block
if(e instanceof FileSizeLimitExceededException)
result = "File size exceeds a predetermined size: " + MAX_FILE_SIZE + "bytes";
return;
e.printStackTrace();
if(list == null || list.size() == 0)
result = "Please select images to upload";
return;
String fileName;
Date now = new Date();
DateFormat dateFormat = DateFormat.getDateInstance();
String date = dateFormat.format(now);
String destDirName = request.getSession()
.getServletContext()
.getRealPath("/")
+ "RawImages\\\\" + date;
File dir = new File(destDirName);
if(!dir.exists() && !dir.isDirectory())
dir.mkdirs();
/*if(!dir.mkdirs())
result = "The server creates image folder failed";
return;
*/
for(FileItem item : list)
fileName = clientIP + "-" + item.getName();
try
File file = new File(destDirName, fileName);
if(file.exists())
continue;
item.write(new File(destDirName, fileName));
catch (Exception e)
// TODO Auto-generated catch block
result = e.getMessage();
e.printStackTrace();
writer.print(result);
以上是关于Android高仿微信图片选择上传工具的主要内容,如果未能解决你的问题,请参考以下文章
Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等