网址:https://github.com/LuckSiege/PictureSelector#%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF
依赖
implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.3'
1.BaseApis
//发表帖子
@POST
Observable<ResponseBody> imagepost(@Url String url, @QueryMap HashMap<String, String> map, @Body MultipartBody parts);
2.RetorfitManager
private MultipartBody build;
//发表帖子
public void imagepost(String url, HashMap<String,String> map, List<File> file, ICallBack callBack){
if(file.size()>0){
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (int i = 0; i < file.size(); i++) {
builder.addFormDataPart("file", file.get(i).getName(), RequestBody.create(MediaType.parse("image/*"), file.get(i)));
}
build = builder.build();
}else{
build=new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("","")
.build();
}
baseApis.imagepost(url, map,build)
.subscribeOn(Schedulers.io())//io子线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getObserver(callBack));
}
Activity
MultipartBody.Builder builder=new MultipartBody.Builder().setType(MultipartBody.FORM);
if(name.equals(""))
{
Toast.makeText(this, "请输入发表的内容!", Toast.LENGTH_SHORT).show();
}else
{
for (int i = 0; i <files.size() ; i++) {
builder.addFormDataPart("file",files.get(i).getName(),RequestBody.create(MediaType.parse("image/*"),files.get(i)));
}
HashMap<String,String> map=new HashMap<>();
map.put("content",name);
//MultipartBody build=builder.build();
iPresentermpl.imagepost(Api.RELEASEPOST,map,files,NewsReplaceBean.class);
}
2.Ativity
public class NewsMessageActivity extends AppCompatActivity implements IView {
@BindView(R.id.edit_num)
TextView edit_num;
@BindView(R.id.messagecontent)
EditText messagecontent;
@BindView(R.id.recycler)
RecyclerView recycler;
PopupWindow popupWindow;
@BindView(R.id.messageok)
TextView messageok;
@BindView(R.id.message_qx)
TextView message_qx;
@BindView(R.id.messqge_yuyin)
TextView messqge_yuyin;
public final static int VEDIO_KU = 101;
IPresentermpl iPresentermpl;
private final int REQUEST_PICK = 200;
private final int REQUEST_CAMEAR = 100;
private final int REQUEST_PICTRUE = 300;
private final String PATH_FILE = Environment.getExternalStorageDirectory() + "/file.png";
// private final String path = Environment.getExternalStorageDirectory() + "/image.png";
private int maxSelectNum = 9;
private List<LocalMedia> selectList = new ArrayList<>();
private GridImageAdapter adapter;
private PopupWindow pop;
private String path;
private List<File> files=new ArrayList<>();
private String userId,sessionId;
private SharedPreferences sharedPreferences;
String[] permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.INTERNET};
List<String> mPermissionList = new ArrayList<>();
private final int mRequestCode = 100;//权限请求码
AlertDialog mPermissionDialog;
String mPackName = "com.wd.tech";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_message);
ButterKnife.bind(this);
iPresentermpl=new IPresentermpl(this);
//Appid
sharedPreferences = getSharedPreferences("User", MODE_PRIVATE);
userId = sharedPreferences.getString("userId", "");
sessionId = sharedPreferences.getString("sessionId", "");
//输入
messagecontent.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
edit_num.setText(String.valueOf(s.length()) + "/300");
if (s.length() >= 300) {
Toast.makeText(NewsMessageActivity.this, "上限了,亲", Toast.LENGTH_SHORT).show();
}
}
}); //逐个判断是否还有未通过的权限
for (int i = 0;i<permissions.length;i++){
if (ContextCompat.checkSelfPermission(this,permissions[i])!=
PackageManager.PERMISSION_GRANTED){
mPermissionList.add(permissions[i]);//添加还未授予的权限到mPermissionList中
}
}
//申请权限
if (mPermissionList.size()>0){//有权限没有通过,需要申请
ActivityCompat.requestPermissions(this,permissions,mRequestCode);
}else {
//权限已经都通过了,可以将程序继续打开了
initWidget();
}
}
@OnClick({R.id.recycler,R.id.messageok,R.id.message_qx,R.id.messqge_yuyin})
public void setlick(View view)
{
switch (view.getId())
{
case R.id.recycler:
break;
case R.id.messageok:
String name=messagecontent.getText().toString();
MultipartBody.Builder builder=new MultipartBody.Builder().setType(MultipartBody.FORM);
if(name.equals(""))
{
Toast.makeText(this, "请输入发表的内容!", Toast.LENGTH_SHORT).show();
}else
{
for (int i = 0; i <files.size() ; i++) {
builder.addFormDataPart("file",files.get(i).getName(),RequestBody.create(MediaType.parse("image/*"),files.get(i)));
}
HashMap<String,String> map=new HashMap<>();
map.put("content",name);
//MultipartBody build=builder.build();
iPresentermpl.imagepost(Api.RELEASEPOST,map,files,NewsReplaceBean.class);
}
finish();
break;
case R.id.message_qx:
finish();
break;
default:break;
}
}
public void initWidget()
{
FullyGridLayoutManager manager = new FullyGridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
recycler.setLayoutManager(manager);
adapter = new GridImageAdapter(this, onAddPicClickListener);
adapter.setList(selectList);
adapter.setSelectMax(maxSelectNum);
recycler.setAdapter(adapter);
adapter.setOnItemClickListener(new GridImageAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, View v) {
if (selectList.size() > 0) {
LocalMedia media = selectList.get(position);
String pictureType = media.getPictureType();
int mediaType = PictureMimeType.pictureToVideo(pictureType);
switch (mediaType) {
case 1:
// 预览图片 可自定长按保存路径
//PictureSelector.create(MainActivity.this).externalPicturePreview(position, "/custom_file", selectList);
PictureSelector.create(NewsMessageActivity.this).externalPicturePreview(position, selectList);
Log.i("aaaaaa地址",selectList+"");
break;
case 2:
// 预览视频
PictureSelector.create(NewsMessageActivity.this).externalPictureVideo(media.getPath());
break;
case 3:
// 预览音频
PictureSelector.create(NewsMessageActivity.this).externalPictureAudio(media.getPath());
break;
}
}
}
});
}
private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
@Override
public void onAddPicClick() {
//第一种方式,弹出选择和拍照的dialog
showPop();
}
};
private void showPop() {
View bottomView = View.inflate(NewsMessageActivity.this, R.layout.layout_bottom_dialog, null);
TextView mAlbum = (TextView) bottomView.findViewById(R.id.tv_album);
TextView mCamera = (TextView) bottomView.findViewById(R.id.tv_camera);
TextView mCancel = (TextView) bottomView.findViewById(R.id.tv_cancel);
pop = new PopupWindow(bottomView, -1, -2);
pop.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
pop.setOutsideTouchable(true);
pop.setFocusable(true);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.5f;
getWindow().setAttributes(lp);
pop.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1f;
getWindow().setAttributes(lp);
}
});
pop.setAnimationStyle(R.style.main_menu_photo_anim);
pop.showAtLocation(getWindow().getDecorView(), Gravity.BOTTOM, 0, 0);
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_album:
//相册
PictureSelector.create(NewsMessageActivity.this)
.openGallery(PictureMimeType.ofImage())
.maxSelectNum(maxSelectNum)
.minSelectNum(1)
.imageSpanCount(4)
.selectionMode(PictureConfig.MULTIPLE)
.forResult(PictureConfig.CHOOSE_REQUEST);
break;
case R.id.tv_camera:
//拍照
PictureSelector.create(NewsMessageActivity.this)
.openCamera(PictureMimeType.ofImage())
.forResult(PictureConfig.CHOOSE_REQUEST);
break;
case R.id.tv_cancel:
//取消
break;
}
closePopupWindow();
}
};
mAlbum.setOnClickListener(clickListener);
mCamera.setOnClickListener(clickListener);
mCancel.setOnClickListener(clickListener);
}
public void closePopupWindow() {
if (pop != null && pop.isShowing()) {
pop.dismiss();
pop = null;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
List<LocalMedia> images;
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PictureConfig.CHOOSE_REQUEST:
// 图片选择结果回调
images = PictureSelector.obtainMultipleResult(data);
selectList.addAll(images);
for (int i = 0; i < selectList.size(); i++) {
path = selectList.get(i).getPath();
files.add(new File(path));
}
adapter.setList(selectList);
adapter.notifyDataSetChanged();
break;
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean hasPermissionDismiss = false;//有权限没有通过
if (mRequestCode==requestCode){
for (int i=0;i<grantResults.length;i++){
if (grantResults[i]==-1){
hasPermissionDismiss=true;
break;
}
}
}
if (hasPermissionDismiss){//如果有没有被允许的权限
showPermissionDialog();
}else {
//权限已经都通过了,可以将程序继续打开了
initWidget();
}
}
private void showPermissionDialog() {
if (mPermissionDialog == null) {
mPermissionDialog = new AlertDialog.Builder(this)
.setMessage("已禁用权限,请手动授予")
.setPositiveButton("设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancelPermissionDialog();
Uri packageURI = Uri.parse("package:" + mPackName);
Intent intent = new Intent(Settings.
ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
startActivity(intent);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//关闭页面或者做其他操作
cancelPermissionDialog();
NewsMessageActivity.this.finish();
}
})
.create();
}
mPermissionDialog.show();
}
private void cancelPermissionDialog() {
mPermissionDialog.cancel();
}
@Override
public void success(Object data) {
if(data instanceof NewsReplaceBean)
{
NewsReplaceBean newsReplaceBean= (NewsReplaceBean) data;
if(newsReplaceBean.getMessage().equals("发布成功"))
{
Toast.makeText(this, "发布成功", Toast.LENGTH_SHORT).show();
}else
{
Toast.makeText(this, "发布失败", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void failure(String error) {
}
}
布局Recycleview
/**
* author:luck
* project:PictureSelector
* package:com.luck.picture.ui
* email:893855882@qq.com
* data:16/12/31
*/
public class FullyGridLayoutManager extends GridLayoutManager {
public FullyGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
int count = getItemCount();
int span = getSpanCount();
for (int i = 0; i < count; i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
if (i % span == 0) {
width = width + mMeasuredDimension[0];
}
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
if (i % span == 0) {
height = height + mMeasuredDimension[1];
}
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
final RecyclerView.State mState = new RecyclerView.State();
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
int itemCount = mState.getItemCount();
if (position < itemCount) {
try {
View view = recycler.getViewForPosition(0);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* author:luck
* project:PictureSelector
* package:com.luck.pictureselector.adapter
* email:893855882@qq.com
* data:16/7/27
*/
public class GridImageAdapter extends
RecyclerView.Adapter<GridImageAdapter.ViewHolder> {
public static final int TYPE_CAMERA = 1;
public static final int TYPE_PICTURE = 2;
private LayoutInflater mInflater;
private List<LocalMedia> list = new ArrayList<>();
private int selectMax = 9;
private Context context;
/**
* 点击添加图片跳转
*/
private onAddPicClickListener mOnAddPicClickListener;
public interface onAddPicClickListener {
void onAddPicClick();
}
public GridImageAdapter(Context context, onAddPicClickListener mOnAddPicClickListener) {
this.context = context;
mInflater = LayoutInflater.from(context);
this.mOnAddPicClickListener = mOnAddPicClickListener;
}
public void setSelectMax(int selectMax) {
this.selectMax = selectMax;
}
public void setList(List<LocalMedia> list) {
this.list = list;
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView mImg;
LinearLayout ll_del;
TextView tv_duration;
public ViewHolder(View view) {
super(view);
mImg = (ImageView) view.findViewById(R.id.fiv);
ll_del = (LinearLayout) view.findViewById(R.id.ll_del);
tv_duration = (TextView) view.findViewById(R.id.tv_duration);
}
}
@Override
public int getItemCount() {
if (list.size() < selectMax) {
return list.size() + 1;
} else {
return list.size();
}
}
@Override
public int getItemViewType(int position) {
if (isShowAddItem(position)) {
return TYPE_CAMERA;
} else {
return TYPE_PICTURE;
}
}
/**
* 创建ViewHolder
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout.item_filter_image,
viewGroup, false);
final ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
private boolean isShowAddItem(int position) {
int size = list.size() == 0 ? 0 : list.size();
return position == size;
}
/**
* 设置值
*/
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
//少于8张,显示继续添加的图标
if (getItemViewType(position) == TYPE_CAMERA) {
viewHolder.mImg.setImageResource(R.drawable.add_img);
viewHolder.mImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnAddPicClickListener.onAddPicClick();
}
});
viewHolder.ll_del.setVisibility(View.INVISIBLE);
} else {
viewHolder.ll_del.setVisibility(View.VISIBLE);
viewHolder.ll_del.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int index = viewHolder.getAdapterPosition();
// 这里有时会返回-1造成数据下标越界,具体可参考getAdapterPosition()源码,
// 通过源码分析应该是bindViewHolder()暂未绘制完成导致,知道原因的也可联系我~感谢
if (index != RecyclerView.NO_POSITION) {
list.remove(index);
notifyItemRemoved(index);
notifyItemRangeChanged(index, list.size());
DebugUtil.i("delete position:", index + "--->remove after:" + list.size());
}
}
});
LocalMedia media = list.get(position);
int mimeType = media.getMimeType();
String path = "";
if (media.isCut() && !media.isCompressed()) {
// 裁剪过
path = media.getCutPath();
} else if (media.isCompressed() || (media.isCut() && media.isCompressed())) {
// 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
path = media.getCompressPath();
} else {
// 原图
path = media.getPath();
}
// 图片
if (media.isCompressed()) {
Log.i("compress image result:", new File(media.getCompressPath()).length() / 1024 + "k");
Log.i("压缩地址::", media.getCompressPath());
}
Log.i("原图地址::", media.getPath());
int pictureType = PictureMimeType.isPictureType(media.getPictureType());
if (media.isCut()) {
Log.i("裁剪地址::", media.getCutPath());
}
long duration = media.getDuration();
viewHolder.tv_duration.setVisibility(pictureType == PictureConfig.TYPE_VIDEO
? View.VISIBLE : View.GONE);
if (mimeType == PictureMimeType.ofAudio()) {
viewHolder.tv_duration.setVisibility(View.VISIBLE);
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.picture_audio);
StringUtils.modifyTextViewDrawable(viewHolder.tv_duration, drawable, 0);
} else {
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.video_icon);
StringUtils.modifyTextViewDrawable(viewHolder.tv_duration, drawable, 0);
}
viewHolder.tv_duration.setText(DateUtils.timeParse(duration));
if (mimeType == PictureMimeType.ofAudio()) {
viewHolder.mImg.setImageResource(R.drawable.audio_placeholder);
} else {
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(R.color.color_4d)
.diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(viewHolder.itemView.getContext())
.load(path)
.apply(options)
.into(viewHolder.mImg);
}
//itemView 的点击事件
if (mItemClickListener != null) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int adapterPosition = viewHolder.getAdapterPosition();
mItemClickListener.onItemClick(adapterPosition, v);
}
});
}
}
}
protected OnItemClickListener mItemClickListener;
public interface OnItemClickListener {
void onItemClick(int position, View v);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mItemClickListener = listener;
}
}
item_filter_image
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerInParent="true">
<ImageView
android:id="@+id/fiv"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:scaleType="centerCrop"
android:src="@color/color_f6"/>
<LinearLayout
android:id="@+id/ll_del"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:gravity="end"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_del"
android:layout_width="25dp"
android:layout_height="25dp"
android:contentDescription="@null"
android:scaleType="fitXY"
android:src="@drawable/delete"/>
</LinearLayout>
<TextView
android:id="@+id/tv_duration"
android:layout_width="80dp"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dp"
android:background="@drawable/buybuybuy"
android:drawableLeft="@drawable/video_icon"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingLeft="5dp"
android:paddingTop="8dp"
android:text="00:00"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
layout_bottom_dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_album"
android:gravity="center"
android:padding="15dp"
android:text="相册"
android:textSize="16sp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#f5f5f5"/>
<TextView
android:id="@+id/tv_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_camera"
android:gravity="center"
android:padding="15dp"
android:text="拍照"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/shape_cancel"
android:gravity="center"
android:padding="15dp"
android:text="取消"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
anim
photo_dialog_in_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromXDelta="0"
android:fromYDelta="1000"
android:toXDelta="0"
android:toYDelta="0" />
</set>
photo_dialog_out_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="1000" />
</set>
Stytle
<style name="main_menu_photo_anim">
<item name="android:windowEnterAnimation">@anim/photo_dialog_in_anim</item>
<item name="android:windowExitAnimation">@anim/photo_dialog_out_anim</item>
</style>