Android使用Retrofit2.0技术仿微信发说说

最近项目做完了,有闲暇时间,一直想做一个类似微信中微信发说说,既能实现拍照,选图库,多图案上传的案例,目前好多App都有类似微信朋友圈的功能,能过发表说说等附带图片上传。下面的就是实现该功能的过程:大家还没有看过Android Retrofit 2.0框架上传图片解决方案(一张与多张的处理)这篇文章,在看今天的就很容易,接在本项目中用到了一个library:photopicker,封装了图片的选择功能,是否选相机,还有选中图片后可以查看图片的功能。

一、 首先:将photopicker到工程中

(1)、先简单讲解一下PhotoPickerIntent的用法:

PhotoPickerIntent intent = new PhotoPickerIntent(MainActivity.this);
  intent.setSelectModel(SelectModel.MULTI); //
  intent.setShowCarema(true); // 是否显示拍照
  intent.setMaxTotal(6); // 最多选择照片数量,默认为6
  intent.setSelectedPaths(imagePaths); // 已选中的照片地址, 用于回显选中状态
  startActivityForResult(intent, REQUEST_CAMERA_CODE);

(2)、设置好之后,重写onActivityResult方法处理选中图片和预览加载适配器

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 if(resultCode == RESULT_OK) {
  switch (requestCode) {
  // 选择照片
  case REQUEST_CAMERA_CODE:
   loadAdpater(data.getStringArrayListExtra(PhotoPickerActivity.EXTRA_RESULT));
   break;
  // 预览
  case REQUEST_PREVIEW_CODE:
   loadAdpater(data.getStringArrayListExtra(PhotoPreviewActivity.EXTRA_RESULT));
   break;
  }
 }
 } 

二、重点在GridAdapter

1.在图片路径中默认添加一图片,用来调用需选择图库
imagePaths.add("000000");

2.根据路径判断选中的图片。如果超过6张,默认路径从集合中移除。

 private class GridAdapter extends BaseAdapter{
 private ArrayList<String> listUrls;
 private LayoutInflater inflater;
 public GridAdapter(ArrayList<String> listUrls) {
  this.listUrls = listUrls;
  if(listUrls.size() == 7){
  listUrls.remove(listUrls.size()-1);
  }
  inflater = LayoutInflater.from(MainActivity.this);
 } 

 public int getCount(){
  return listUrls.size();
 }
 @Override
 public String getItem(int position) {
  return listUrls.get(position);
 } 

 @Override
 public long getItemId(int position) {
  return position;
 } 

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder = null;
  if (convertView == null) {
  holder = new ViewHolder();
  convertView = inflater.inflate(R.layout.item_image, parent,false);
  holder.image = (ImageView) convertView.findViewById(R.id.imageView);
  convertView.setTag(holder);
  } else {
  holder = (ViewHolder)convertView.getTag();
  } 

  final String path=listUrls.get(position);
  if (path.equals("000000")){
  holder.image.setImageResource(R.mipmap.ic_launcher);
  }else {
  Glide.with(MainActivity.this)
   .load(path)
   .placeholder(R.mipmap.default_error)
   .error(R.mipmap.default_error)
   .centerCrop()
   .crossFade()
   .into(holder.image);
  }
  return convertView;
 }
  class ViewHolder {
  ImageView image;
 }
 }
}

三、上传管理类

/**
 * Created by lidong on 2016/1/28.
 */
public class FileUploadManager { 

 private static final String ENDPOINT = "http://192.168.1.21:8080";
 private static String TAG = FileUploadManager.class.getSimpleName(); 

 public interface FileUploadService {
 /**
  * 上传一张图片
  * @param description
  * @param imgs
  * @return
  */
 @Multipart
 @POST("/upload")
 Call<String> uploadImage(@Part("fileName") String description,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs); 

 /**
  * 上传6张图片
  * @param description
  * @param imgs1
  * @param imgs2
  * @param imgs3
  * @param imgs4
  * @param imgs5
  * @param imgs6
  * @return
  */
 @Multipart
 @POST("/upload")
 Call<String> uploadImage(@Part("description") String description,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs1,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs2,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs3,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs4,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs5,
     @Part("file\"; filename=\"image.png\"") RequestBody imgs6); 

 /**
  * 简便写法
  * @param description
  * @param imgs1
  * @return
  */
 @Multipart
 @POST("/upload")
 Call<String> uploadImage(@Part("description") String description,@PartMap
     Map<String, RequestBody> imgs1);
 } 

 private static final Retrofit sRetrofit = new Retrofit .Builder()
  .baseUrl(ENDPOINT)
  .addConverterFactory(GsonConverterFactory.create())
  .build(); 

 private static final FileUploadService apiManager = sRetrofit.create(FileUploadService.class); 

 /**
 * 发说说
 * @param paths
 * @param desp
 */
 public static void upload(ArrayList<String> paths,String desp){
 RequestBody[] requestBody= new RequestBody[6];
 if (paths.size()>0) {
  for (int i=0;i<paths.size();i++) {
  requestBody[i] =
   RequestBody.create(MediaType.parse("multipart/form-data"), new File(paths.get(i)));
  }
 }
 Call<String> call = apiManager.uploadImage( desp,requestBody[0],requestBody[1],requestBody[2],requestBody[3],requestBody[4],requestBody 

[5]);
 call.enqueue(new Callback<String>() {
  @Override
  public void onResponse(Call<String> call, Response<String> response) {
  Log.d(TAG, "onResponse() called with: " + "call = [" + call + "], response = [" + response + "]");
  } 

  @Override
  public void onFailure(Call<String> call, Throwable t) {
  Log.d(TAG, "onFailure() called with: " + "call = [" + call + "], t = [" + t + "]");
  }
 }); 

 }<pre name="code" class="java"> /**
 *
 * @param paths
 * @param desp
 */
 public static void uploadMany(ArrayList<String> paths,String desp){
 Map<String,RequestBody> photos = new HashMap<>();
 if (paths.size()>0) {
  for (int i=0;i<paths.size();i++) {
  String substring = paths.get(i).substring(paths.get(i).lastIndexOf("/") + 1, paths.get(i).length());
  photos.put("file\"; filename="+substring, RequestBody.create(MediaType.parse("multipart/form-data"), new File(paths.get(i))));
  }
 }
 Call<String> stringCall = apiManager.uploadImage(desp, photos);
 stringCall.enqueue(new Callback<String>() {
  @Override
  public void onResponse(Call<String> call, Response<String> response) {
  Log.d(TAG, "onResponse() called with: " + "call = [" + call + "], response = [" + response + "]");
  } 

  @Override
  public void onFailure(Call<String> call, Throwable t) {
  Log.d(TAG, "onFailure() called with: " + "call = [" + call + "], t = [" + t + "]");
  }
 });
 }

四、项目代码

package com.lidong.photopickersample; 

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView; 

import com.bumptech.glide.Glide;
import com.lidong.photopicker.ImageCaptureManager;
import com.lidong.photopicker.PhotoPickerActivity;
import com.lidong.photopicker.PhotoPreviewActivity;
import com.lidong.photopicker.SelectModel;
import com.lidong.photopicker.intent.PhotoPickerIntent;
import com.lidong.photopicker.intent.PhotoPreviewIntent; 

import org.json.JSONArray; 

import java.util.ArrayList; 

/**
 * @
 * @author lidong
 * @date 2016-02-29
 */
public class MainActivity extends AppCompatActivity { 

 private static final int REQUEST_CAMERA_CODE = 10;
 private static final int REQUEST_PREVIEW_CODE = 20;
 private ArrayList<String> imagePaths = new ArrayList<>();
 private ImageCaptureManager captureManager; // 相机拍照处理类 

 private GridView gridView;
 private GridAdapter gridAdapter;
 private Button mButton;
 private String depp;
 private EditText textView;
 private String TAG =MainActivity.class.getSimpleName(); 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 gridView = (GridView) findViewById(R.id.gridView);
 mButton = (Button) findViewById(R.id.button);
 textView= (EditText)findViewById(R.id.et_context); 

 int cols = getResources().getDisplayMetrics().widthPixels / getResources().getDisplayMetrics().densityDpi;
 cols = cols < 3 ? 3 : cols;
 gridView.setNumColumns(cols); 

 // preview
 gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  String imgs = (String) parent.getItemAtPosition(position);
  if ("000000".equals(imgs) ){
   PhotoPickerIntent intent = new PhotoPickerIntent(MainActivity.this);
   intent.setSelectModel(SelectModel.MULTI);
   intent.setShowCarema(true); // 是否显示拍照
   intent.setMaxTotal(6); // 最多选择照片数量,默认为6
   intent.setSelectedPaths(imagePaths); // 已选中的照片地址, 用于回显选中状态
   startActivityForResult(intent, REQUEST_CAMERA_CODE);
  }else{
   PhotoPreviewIntent intent = new PhotoPreviewIntent(MainActivity.this);
   intent.setCurrentItem(position);
   intent.setPhotoPaths(imagePaths);
   startActivityForResult(intent, REQUEST_PREVIEW_CODE);
  }
  }
 });
 imagePaths.add("000000");
 gridAdapter = new GridAdapter(imagePaths);
 gridView.setAdapter(gridAdapter);
 mButton.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  depp =textView.getText().toString().trim()!=null?textView.getText().toString().trim():"woowoeo";
  new Thread(){
   @Override
   public void run() {
   super.run();
   FileUploadManager.uploadMany(imagePaths, depp);
//   FileUploadManager.upload(imagePaths,depp);
   }
  }.start();
  }
 });
 } 

 @Override
 protected void onResume() {
 super.onResume();
 } 

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 if(resultCode == RESULT_OK) {
  switch (requestCode) {
  // 选择照片
  case REQUEST_CAMERA_CODE:
   ArrayList<String> list = data.getStringArrayListExtra(PhotoPickerActivity.EXTRA_RESULT);
   Log.d(TAG, "list: " + "list = [" + list.size());
   loadAdpater(list);
   break;
  // 预览
  case REQUEST_PREVIEW_CODE:
   ArrayList<String> ListExtra = data.getStringArrayListExtra(PhotoPreviewActivity.EXTRA_RESULT);
   Log.d(TAG, "ListExtra: " + "ListExtra = [" + ListExtra.size());
   loadAdpater(ListExtra);
   break;
  }
 }
 } 

 private void loadAdpater(ArrayList<String> paths){
 if (imagePaths!=null&& imagePaths.size()>0){
  imagePaths.clear();
 }
 if (paths.contains("000000")){
  paths.remove("000000");
 }
 paths.add("000000");
 imagePaths.addAll(paths);
 gridAdapter = new GridAdapter(imagePaths);
 gridView.setAdapter(gridAdapter);
 try{
  JSONArray obj = new JSONArray(imagePaths);
  Log.e("--", obj.toString());
 }catch (Exception e){
  e.printStackTrace();
 }
 } 

 private class GridAdapter extends BaseAdapter{
 private ArrayList<String> listUrls;
 private LayoutInflater inflater;
 public GridAdapter(ArrayList<String> listUrls) {
  this.listUrls = listUrls;
  if(listUrls.size() == 7){
  listUrls.remove(listUrls.size()-1);
  }
  inflater = LayoutInflater.from(MainActivity.this);
 } 

 public int getCount(){
  return listUrls.size();
 }
 @Override
 public String getItem(int position) {
  return listUrls.get(position);
 } 

 @Override
 public long getItemId(int position) {
  return position;
 } 

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder = null;
  if (convertView == null) {
  holder = new ViewHolder();
  convertView = inflater.inflate(R.layout.item_image, parent,false);
  holder.image = (ImageView) convertView.findViewById(R.id.imageView);
  convertView.setTag(holder);
  } else {
  holder = (ViewHolder)convertView.getTag();
  } 

  final String path=listUrls.get(position);
  if (path.equals("000000")){
  holder.image.setImageResource(R.mipmap.ic_launcher);
  }else {
  Glide.with(MainActivity.this)
   .load(path)
   .placeholder(R.mipmap.default_error)
   .error(R.mipmap.default_error)
   .centerCrop()
   .crossFade()
   .into(holder.image);
  }
  return convertView;
 }
  class ViewHolder {
  ImageView image;
 }
 }
}

五、SpringMVC接收文件的action

 public String addUser(@RequestParam("file") CommonsMultipartFile[] files,
  HttpServletRequest request){ 

 for(int i = 0;i<files.length;i++){
  System.out.println("fileName---------->" + files[i].getOriginalFilename()); 

  if(!files[i].isEmpty()){
  int pre = (int) System.currentTimeMillis();
  try {
   //拿到输出流,同时重命名上传的文件
   FileOutputStream os = new FileOutputStream("f:/img"+"/" + new Date().getTime()+".jpg");
   //拿到上传文件的输入流
   FileInputStream in = (FileInputStream) files[i].getInputStream(); 

   //以写字节的方式写文件
   int b = 0;
   while((b=in.read()) != -1){
   os.write(b);
   }
   os.flush();
   os.close();
   in.close();
   int finaltime = (int) System.currentTimeMillis();
   System.out.println(finaltime - pre); 

  } catch (Exception e) {
   e.printStackTrace();
   System.out.println("上传出错");
  }
 }
 }
 return "/success";
 } 

 六、Struts2接收文件

public class UploadFile extends ActionSupport { 

 /**
 *
 */
private static final long serialVersionUID = 1L; 

private File[] file;//文件数组
private String description;//说说内容
public File[] getFile() {
 return file;
}
public void setFile(File[] file) {
 this.file = file;
} 

public String getDescription() {
 return description;
}
public void setDescription(String description) {
 this.description = description;
}
@Action("/upload")
public void upload() {
 System.out.println("上传的文件="+Arrays.toString(file));
 System.out.println("说说内容="+description);
}
}

项目下载地址:https://github.com/lidong1665/Android-UploadMultipartImage

效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android Retrofit的简单介绍和使用

    Retrofit与okhttp共同出自于Square公司,retrofit就是对okhttp做了一层封装.把网络请求都交给给了Okhttp,我们只需要通过简单的配置就能使用retrofit来进行网络请求了,其主要作者是Android大神JakeWharton. 导包: compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'//Retrofit2所需要的包 compile 'com.squareup.retrofit2:converter-gso

  • Android app开发中Retrofit框架的初步上手使用

    Retrofit 2.0 先来说一下Retrofit 2.0版本中一些引人注意的地方. 在Retrofit 2.0中,最大的改动莫过于减小库的体积,首先,Retrofit 2.0去掉了对所有的HTTP客户端的兼容,而钟情于OkHttpClient一个,极大地减少了各种适配代码,原因一会儿说;其次,拆库,比如将对RxJava的支持设置为可选(需要额外引入库):再比如将各个序列化反序列化转换器支持设置为可选(需要额外引入库).于2.0抛弃HttpClient和HttpURLConnection,为了

  • Android中的Retrofit+OkHttp+RxJava缓存架构使用

    RxJava如何与Retrofit结合 先扔出build.gradle文件的内容 dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.0' compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxand

  • Android Retrofit 2.0框架上传图片解决方案

    本文为大家分享了 Android Retrofit 2.0框架上传图片解决方案,具体内容如下 1.单张图片的上传 /** * 上传一张图片 * @param description * @param imgs * @return */ @Multipart @POST("/upload") Call<String> uploadImage(@Part("fileName") String description, @Part("file\&qu

  • 简略分析Android的Retrofit应用开发框架源码

    面对一个项目,对于Android应用开发框架的选择,我想过三种方案: 1.使用Loader + HttpClient + GreenDao + Gson + Fragment,优点是可定制性强,由于使用Google家自己的Loader和LoaderManager,代码健壮性强. 缺点是整套代码学习成本较高,使用过程中样板代码较多,(比如每一个Request都需要产生一个新类) 2.Volley,作为Google在IO大会上得瑟过的一个网络库,其实不算什么新东西(2013 IO发布),使用较为简单

  • Android中Retrofit+OkHttp进行HTTP网络编程的使用指南

    Retrofit介绍: Retrofit(GitHub主页https://github.com/square/okhttp)和OkHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdapter,Converter,你可以使用不同的请求适配器(CallAdapter), 比方说RxJava,Java8, Guava.你可以使用不同的反序列化工具

  • Android中okhttp3.4.1+retrofit2.1.0实现离线缓存

    关于Retrofit+OkHttp的强大这里就不多说了,还没了解的同学可以自行去百度.这篇文章主要讲如何利用Retrofit+OkHttp来实现一个较为简单的缓存策略: 即有网环境下我们请求数据时,如果没有缓存或者缓存过期了,就去服务器拿数据,并且将新缓存保存下来,如果有缓存而且没有过期,则直接使用缓存.无网环境下我们请求数据时,缓存没过期则直接使用缓存,缓存过期了则无法使用,需要重新联网获取服务器数据. 缓存处理还是很有必要的,它有效的减少服务器负荷,降低延迟提升用户体验,同时也方便用户即使在

  • Android使用Retrofit仿微信多张图片拍照上传

    Android 仿照微信发说说,既能实现拍照,选图库,多图案上传,使用Retrofit技术. 使用方法:详见http://www.jb51.net/article/103009.htm 项目的运行效果: 服务器端接收文件的action UploadFile.java @Controller public class UploadFile extends ActionSupport { /** * */ private static final long serialVersionUID = 1L

  • Android Retrofit文件下载进度显示问题的解决方法

    综述 在Retrofit2.0使用详解这篇文章中详细介绍了retrofit的用法.并且在retrofit中我们可以通过ResponseBody进行对文件的下载.但是在retrofit中并没有为我们提供显示下载进度的接口.在项目中,若是用户下载一个文件,无法实时给用户显示下载进度,这样用户的体验也是非常差的.那么下面就介绍一下在retrofit用于文件的下载如何实时跟踪下载进度. 演示 Retrofit文件下载进度更新的实现 在retrofit2.0中他依赖于Okhttp,所以如果我们需要解决这个

  • Android使用Retrofit2.0技术仿微信发说说

    最近项目做完了,有闲暇时间,一直想做一个类似微信中微信发说说,既能实现拍照,选图库,多图案上传的案例,目前好多App都有类似微信朋友圈的功能,能过发表说说等附带图片上传.下面的就是实现该功能的过程:大家还没有看过Android Retrofit 2.0框架上传图片解决方案(一张与多张的处理)这篇文章,在看今天的就很容易,接在本项目中用到了一个library:photopicker,封装了图片的选择功能,是否选相机,还有选中图片后可以查看图片的功能. 一. 首先:将photopicker到工程中

  • Android仿微信发朋友圈浏览图片效果

    先看一下效果吧: 下面就来说一下具体怎么实现的: 实现思路 1.首先我们要获取数据源,数据源就是我们的每条说说(包括姓名.标题.图片数组) 2.自定义适配器(ListView嵌套着GridView) 3.图片点击浏览图片(Fragment+ViewPager) 具体实现 1.初始化数据源,设置适配器,看一下代码: public class MyActivity extends Activity { /*图片显示列表*/ private ListView listView; /*图片URL数组*/

  • Android 仿微信发动态九宫格拖拽、删除功能

    1.完美1比1 仿照微信仿微信发动态 九宫格拖拽.删除 暴力拖拽ui有点问题,不影响使用,资源文件自己找个+号 2.微信发动态拖拽bug 当选择完图片,长按图片拖拽过程中按下屏幕home键盘,再次进入这时候就不能点击输入文字,点击输入文字的时候会触发选择相册事件 3.拖拽事件用的basequickadapter implementation 'com.android.support:recyclerview-v7:28.0.0' implementation "com.github.CymCha

  • Android实现录音方法(仿微信语音、麦克风录音、发送语音、解决5.0以上BUG)

    先给大家展示下效果图,如果大家感觉不错,请参考使用方法, 效果图如下所示: 使用方法: 录音工具类:AudioRecoderUtils.java,代码如下: public class AudioRecoderUtils { //文件路径 private String filePath; //文件夹路径 private String FolderPath; private MediaRecorder mMediaRecorder; private final String TAG = "fan&q

  • Android中使用GridView实现仿微信图片上传功能(附源代码)

    由于工作要求最近在使用GridView完成图片的批量上传功能,我的例子当中包含仿微信图片上传.拍照.本地选择.相片裁剪等功能,如果有需要的朋友可以看一下,希望我的实际经验能对您有所帮助. 直接上图,下面的图片就是点击"加号"后弹出的对话框,通过对话框可以根据自己需求进行相片选择. 项目结构: 下面直接上代码. 整体的布局文件activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/

  • PHP仿微信发红包领红包效果

    近期项目需要在聊天的基础上新增红包功能,需求:仿微信(不含留言),但只能使用余额发红包.于是多次使用微信红包,了解各种交互界面及业务需求,如展示信息.分类(个人,群普通,群拼手气).个数限制(100).金额限制(200).过期时间(24小时)等等,然后着手开发,下面提及的基本全是提供给app端的接口,毕竟我是phper. 一.设计数据表如下 CREATE TABLE `red_packet` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `us

  • Android高德地图poi检索仿微信发送位置实例代码

    最近项目需求把发送定位模块改成类似微信发送位置给好友的效果,我使用了高德地图实现了一个demo,效果图如下: 从主界面中我们可以看到中心标记上面显示的就是我们定位的地址,下面是一个listview列表,第一条item的数据就是我们定位得到的地址,下面其余的都是我们根据定位得到的经纬度通过poi周边搜索得到的地址.我们进行了如下操作: 我们点击列表的item,中心标记会移动到该item对象的地址上面去. 我们手动移动地图的时候,中心标记的地址会发生相应的变化并且下面的列表也会发生相应的变化. 根据

  • 利用百度地图Android sdk高仿微信发送位置功能及遇到的问题

    接触了百度地图开发平台半个月了,这2天试着模仿了微信给好友发送位置功能,对百度地图的操作能力又上了一个台阶 我在实现这个功能的时候,遇到一些困难,可能也是别人将会遇到的困难,特在此列出 1.在微信发送功能中,不管用户如何拖拽地图,总有个覆盖物固定了MapView中央,怎么实现? 其实这很容易实现,只要MapView的布局文件中,将一个ImageView覆盖在MapView的中央,就能够实现不管用户如何拖拽地图,覆盖物(ImageView)总固定总MapView中央 2.如何获取MapView中央

  • Android仿微信图片上传带加号且超过最大数隐藏功能

    1.仿照微信空间上传图片,显示图片数量以及超过最大,上传按钮隐藏功能 2.上效果图 3.上代码,主要是Adapter类 /** * Created by zhangyinlei on 2018/3/2 0002. */ public class AlbumSelectedShowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static int TYPE_ADD = 0;//添加图片 privat

  • Android GridView扩展仿微信微博发图动态添加删除图片功能

    在平时的开发中,我们会看到不管是微信发朋友圈照片还是微博发布新鲜事,添加图片的时候都是选完后面还有个+号再去选择图片,这样的话比较方便用户去添加图片,有的右上角还有个-号方便用户去删除图片,而一般用户选择的图片多少都是不定的,我们只限制最大张数,我们用gridview去实现,代码可能比较简单,高手请略过. 0.效果图 1.准备资源图片 添加图片的+号图片 删除图片的图片 2.可设置限制用户选择最大张数 /** * 可以动态设置最多上传几张,之后就不显示+号了,用户也无法上传了 * 默认9张 */

随机推荐