因为项目中需要用到头像上传的功能,所以就下个Ddmo先来实现下。

demo我是类似仿微信的,在一个GridView中展示所有的图片,其中第一个item可以去照相;获取到图片后再进行剪切。

图片的剪切是从网上找的感觉不错就用,暂时也没有测试。

获取图片可以用:https://github.com/lovetuzitong/MultiImageSelector来实现

这里的圆形图像是用https://github.com/hdodenhof/CircleImageView来实现的

Demo写的比较粗糙,效果只是在4.4的手机和7.0的模拟器跑了一遍,所以可能会出现问题的。

下载资源:http://download.csdn.net/download/qq_29774291/9955206

如下是demo的效果图:

如下是选择图片中的代码

通过LoaderManager来获取到所有的图片,然后第一个进行拍照的处理

 package com.item.demo.photo.activity;

 import android.Manifest;
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView; import com.item.demo.photo.BuildConfig;
import com.item.demo.photo.R;
import com.item.demo.photo.adapter.MyPhotoAdapter;
import com.item.demo.photo.uilts.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.List; /**
* 图片选择界面
*/
public class MyPhotoActivity extends AppCompatActivity { private static final int REQUEST_CAPTURE = 100;
//private static final int REQUEST_PICK = 101;
private static final int REQUEST_CROP_PHOTO = 102; public static final int FINSH_RESULT = 104;//截图后的返回 private static final int LOADER_ID = 0x0100;
private LoadCallBack mLoad = new LoadCallBack(); private MyPhotoAdapter mAdapter;
private List<Image> images = new ArrayList<>();
//调用照相机返回图片文件
private File tempFile;
private static final int MIN_IMAGE_FILE_SIZE = 10 * 1024; // 最小的图片大小 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_photo); GridView gv_photo = (GridView)findViewById(R.id.gv_photo);
ImageView img_back = (ImageView)findViewById(R.id.iv_back);
images.add(new Image());
mAdapter = new MyPhotoAdapter(this,images);
gv_photo.setAdapter(mAdapter);
gv_photo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if(i == 0){
//第一个就去照相
if(hasPermission(new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})){
gotoCamera();
}else {
requestPermission(0x02,new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE});
}
}else {
//这里点击获取到图片地址然后裁剪
gotoClipActivity(Uri.parse(images.get(i).getPath()));
}
}
});
img_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
} @Override
protected void onStart() {
super.onStart(); if(hasPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE})){
getLoaderManager().initLoader(LOADER_ID,null,mLoad);
}else {
requestPermission(0x01,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE});
}
} private class LoadCallBack implements LoaderManager.LoaderCallbacks<Cursor>{
private final String[] IMAGE_PROJECTION = new String[]{
MediaStore.Images.Media._ID,//Id
MediaStore.Images.Media.DATA,//图片路径
MediaStore.Images.Media.DATE_ADDED//图片的创建时间
}; @Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
//创建一个Loader
if(id == LOADER_ID){
//如果是我们的ID则进行初始化
return new CursorLoader(getBaseContext(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_PROJECTION,
null,
null,
IMAGE_PROJECTION[2] + " DESC");
}
return null;
} @Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//当Loader加载完成时
List<Image> images = new ArrayList<>();
//判断是否有数据
if(data != null){
int count = data.getCount();
if(count > 0){
data.moveToFirst();
// 得到对应的列的Index坐标
int indexId = data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]);
int indexPath = data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]);
int indexDate = data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]);
do {
// 循环读取,直到没有下一条数据
int id = data.getInt(indexId);
String path = data.getString(indexPath);
long dateTime = data.getLong(indexDate); File file = new File(path);
if (!file.exists() || file.length() < MIN_IMAGE_FILE_SIZE) {
// 如果没有图片,或者图片大小太小,则跳过
continue;
}
// 添加一条新的数据
Image image = new Image();
image.setId(id);
image.setPath(path);
image.setDate(dateTime);
images.add(image); } while (data.moveToNext());
}
}
updateSource(images);
} @Override
public void onLoaderReset(Loader<Cursor> loader) {
updateSource(null);
}
} /**
* 通知Adapter数据更改的方法
* @param images 新的数据
*/
private void updateSource(List<Image> images){
this.images.clear();
this.images.add(new Image());
if(images == null || images.size() == 0) return;
this.images.addAll(images);
mAdapter.notifyDataSetChanged();
} /**
*权限的返回
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode){
case 0x02:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
gotoCamera();
}
break;
case 0x01:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
getLoaderManager().initLoader(LOADER_ID,null,mLoad);
}
}
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case REQUEST_CAPTURE://系统相机返回
if(resultCode == RESULT_OK){
Log.d("jiejie","--------相机---------" + Uri.fromFile(tempFile).toString());
Log.d("jiejie","--------path----------" + getRealFilePathFromUri(MyPhotoActivity.this,Uri.fromFile(tempFile)));
gotoClipActivity(Uri.fromFile(tempFile));
} break;
case REQUEST_CROP_PHOTO:
if(resultCode == RESULT_OK){
if(data != null){
Uri uri = data.getData();
Log.d("jiejie","-------------" + data.getData().getPath());
String cropImagePath = getRealFilePathFromUri(MyPhotoActivity.this,uri);
Log.d("jiejie","------crop--------" + cropImagePath);
Intent intent = new Intent();
intent.putExtra("image",cropImagePath);
setResult(FINSH_RESULT,intent);
MyPhotoActivity.this.finish();
} }
break;
}
} /**
* 跳转到系统照相机
*/
private void gotoCamera(){
String SDState = Environment.getExternalStorageState();
//判断SD卡是否存在
if(SDState.equals(Environment.MEDIA_MOUNTED)){
tempFile = new File(checkDirPath(Environment.getExternalStorageDirectory().getPath()+ "/image/"), System.currentTimeMillis() + ".jpg");
//隐式的打开调用系统相册
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//如果是7.0及以上的系统使用FileProvider的方式创建一个Uri
Uri contentUri = FileProvider.getUriForFile(MyPhotoActivity.this, BuildConfig.APPLICATION_ID + ".fileProvider", tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
}else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
}
startActivityForResult(intent,REQUEST_CAPTURE);
}
} /**
* 打开截图的界面
* @param uri
*/
private void gotoClipActivity(Uri uri){
if(uri == null){
return;
}
Intent intent = new Intent(this,ClipImageActivity.class);
intent.putExtra("type",1);
intent.setData(uri);
startActivityForResult(intent,REQUEST_CROP_PHOTO);
} /**
* 检查文件是否存在
*/
private static String checkDirPath(String dirPath) {
if (TextUtils.isEmpty(dirPath)) {
return "";
}
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
return dirPath;
}
/**
* 判断是否有指定的权限
*/
public boolean hasPermission(String... permissions) { for (String permisson : permissions) {
if (ContextCompat.checkSelfPermission(this, permisson)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 申请指定的权限.
*/
public void requestPermission(int code, String... permissions) { if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(permissions, code);
}
} /**
* 根据Uri返回文件绝对路径
* 兼容了file:///开头的 和 content://开头的情况
*/
public static String getRealFilePathFromUri(final Context context, final Uri uri) {
if (null == uri) return null;
final String scheme = uri.getScheme();
String data = null;
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
}

适配器的代码:

package com.item.demo.photo.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.item.demo.photo.R;
import com.item.demo.photo.uilts.Image; import java.util.List; /**
* 图片的适配器
* Created by Administrator on 2017/8/25.
*/ public class MyPhotoAdapter extends BaseAdapter {
private Context mContext;
private List<Image> mData; public MyPhotoAdapter(Context mContext, List<Image> mData) {
this.mContext = mContext;
this.mData = mData;
} @Override
public int getCount() {
return mData.size();
} @Override
public Object getItem(int i) {
return null;
} @Override
public long getItemId(int i) {
return 0;
} @Override
public View getView(int position, View view, ViewGroup viewGroup) {
ViewHolder holder;
if(view == null){
holder = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.adapter_cell_layout,null);
holder.mPic = view.findViewById(R.id.item_image);
holder.mShade = view.findViewById(R.id.item_shade);
view.setTag(holder);
}else {
holder = (ViewHolder) view.getTag();
}
if(position < 1){
//第一个Item 特殊待遇下
holder.mShade.setVisibility(View.GONE);
Glide.with(mContext).load(R.drawable.ic_photo_add)
.into(holder.mPic);
}else {
GlideApp.with(mContext)
.load(mData.get(position).getPath())
.diskCacheStrategy(DiskCacheStrategy.NONE)
.centerCrop()
.placeholder(R.color.color_photo)
.into(holder.mPic);
// Glide.with(mContext)
// .load(mData.get(position).getPath())//加载路径
// .diskCacheStrategy(DiskCacheStrategy.NONE)//不适用缓存
// .centerCrop()//居中剪切
// .placeholder(R.color.color_photo)//默认颜色
// .into(holder.mPic);
} return view;
}
static class ViewHolder{
private ImageView mPic;
private View mShade;
}
}

其中处理动态的权限还需要添加7.0的照相处理

在清单文件中加如下配置:

        <provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.item.demo.photo.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

图片的剪切

package com.item.demo.photo.activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.item.demo.photo.R;
import com.item.demo.photo.view.ClipViewLayout;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream; /**
* 图片剪切
*/
public class ClipImageActivity extends AppCompatActivity implements View.OnClickListener { private ClipViewLayout clipViewLayout1;
private ClipViewLayout clipViewLayout2;
private ImageView back;
private TextView tv_ok;
//类别 1:圆形 2:方形
private int type; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clip_image);
type = getIntent().getIntExtra("type",1);
initView();
} private void initView() {
clipViewLayout1 = (ClipViewLayout)findViewById(R.id.clipViewLayout1);
clipViewLayout2 = (ClipViewLayout)findViewById(R.id.clipViewLayout2);
back = (ImageView)findViewById(R.id.iv_back);
tv_ok = (TextView)findViewById(R.id.tv_ok);
back.setOnClickListener(this);
tv_ok.setOnClickListener(this);
} @Override
protected void onResume() {
super.onResume();
if(type == 1){
clipViewLayout1.setVisibility(View.VISIBLE);
clipViewLayout2.setVisibility(View.GONE);
//设置图片资源
clipViewLayout1.setImageSrc(getIntent().getData());
}else {
clipViewLayout2.setVisibility(View.VISIBLE);
clipViewLayout1.setVisibility(View.GONE);
clipViewLayout2.setImageSrc(getIntent().getData());
}
} @Override
public void onClick(View view) {
switch (view.getId()){
case R.id.iv_back:
finish();
break;
case R.id.tv_ok:
generateUriAndReturn();
break;
}
} /**
* 生成Uri并且通过setResult返回给打开的Activity
*/
private void generateUriAndReturn() {
//调用返回剪切图
Bitmap zoomedCropBitmap;
if (type == 1) {
zoomedCropBitmap = clipViewLayout1.clip();
} else {
zoomedCropBitmap = clipViewLayout2.clip();
}
if (zoomedCropBitmap == null) {
Log.e("android", "zoomedCropBitmap == null");
return;
}
Uri mSaveUri = Uri.fromFile(new File(getCacheDir(), "cropped_" + System.currentTimeMillis() + ".jpg"));
if (mSaveUri != null) {
OutputStream outputStream = null;
try {
outputStream = getContentResolver().openOutputStream(mSaveUri);
if (outputStream != null) {
zoomedCropBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
}
} catch (IOException ex) {
Log.e("android", "Cannot open file: " + mSaveUri, ex);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Intent intent = new Intent();
intent.setData(mSaveUri);
setResult(RESULT_OK, intent);
finish();
}
}
}

android头像上传(获取头像加剪切)的更多相关文章

  1. Android图片上传(头像裁切+原图原样)

    下面简单铺一下代码: (一)头像裁切.上传服务器(代码) 这里上边的按钮是头像的点击事件,弹出底部的头像选择框,下边的按钮跳到下个页面,进行原图上传. ? 1 2 3 4 5 6 7 8 9 10 1 ...

  2. 微信小程序--更换用户头像/上传用户头像/更新用户头像

    changeAvatar:function (){ var that=this; wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'c ...

  3. Canvas处理头像上传

    未分类 最近社区系统需要支持移动端,其中涉及到用户头像上传,头像有大中小三种尺寸,在PC端,社区用Flash来处理头像编辑和生成,但该Flash控件的界面不友好而且移动端对Flash的支持不好,考虑到 ...

  4. 【Bootstrap-插件使用】Jcrop+fileinput组合实现头像上传功能

    作者:Dreawer链接:https://zhuanlan.zhihu.com/p/24465742来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:梦游的龙猫(转 ...

  5. [Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能

    很久没有更新博客了,再不写点东西都烂了. 这次更新一个小内容,是两个插件的组合使用,实现头像上传功能. 业务需求: 头像上传功能,要对上传的文件进行剪切,且保证头像到服务器时必须是正方形的. 优化&l ...

  6. ASP.NET简单实现APP中用户个人头像上传和裁剪

    最近有个微信项目的用户个人中心模块中,客户要求用户头像不仅仅只是上传图片,还需要能对图片进行裁剪.考虑到flash在IOS和Android上的兼容性问题,于是想着能从js这块入手,在网上发现了devo ...

  7. qt实现头像上传功能

    想必大家都使用过qt的自定义头像功能吧,那么图1应该不会陌生,本片文章我就是要模拟一个这样的功能,虽然没有这么强大的效果,但是能够满足一定的需求. 图1 qq上传图片 首先在讲解功能之前,我先给出一片 ...

  8. 升级IOS8游戏上传自定义头像功能失效的问题

    为了支持arm64,之前已经折腾了很久,昨晚打包准备提交苹果审核时,测试那边的同事反馈说游戏上传自定义头像功能不可用了. 游戏上传自定义功能的简介:卡牌游戏最初是<比武招亲>中有一个充VI ...

  9. Django 自带 user 字段扩展及头像上传

    django 及 rest_framework 笔记链接如下: django 入门笔记:环境及项目搭建 django 入门笔记:数据模型 django 入门笔记:视图及模版 django 入门笔记:A ...

随机推荐

  1. JDK7 AutoCloseable

    干嘛的 直接看JDK7的流(运用了AutoCloseable)源码 public abstract class InputStream implements Closeable { //实现Close ...

  2. 数据库其他注入思路 - 万能密码 - cookie注入 -搜索型注入

    另类登录注入形式: 经常有一类验证(ASP,PHP,JSP均存在),先判断user是否存在,ASP为例子:"select password from admin where user_nam ...

  3. [问题解决]gradle编译失败系统找不到指定的文件

    [问题解决]gradle编译失败系统找不到指定的文件 问题描述 Error:C:\Users\diql.gradle\caches\2.14.1\scripts-remapped\settings_9 ...

  4. AngularJS 的常用特性(四)

    11.使用 Module(模块) 组织依赖关系 Angular 里面的模板,提供了一种方法,可以用来组织应用中一块功能区域的依赖关系:同时还提供了一种机制,可以自动解析依赖关系(又叫依赖注入),一般来 ...

  5. Postgresql 连接更新

    update dbo.m_role_fun a set role_code = b.rsc from (select rsc, fun_code from dbo.m_fun) b where a.f ...

  6. [转]Vue.js 目录结构

    本文转自:http://www.runoob.com/vue2/vue-directory-structure.html 上一章节中我们使用了 npm 安装项目,我们在 IDE(Eclipse.Ato ...

  7. jQuery 表格中实现“删除线”的增进方法

    之前做了一个删除线的效果,就是类似这样的,在内容的中间加一条线. 但是又有点不同的是,这种删除线不是单纯的在文字之上,而是给一个Table中的一行加上这种删除线效果. 这里有两个方法,是在不同时期写的 ...

  8. MapReduce详解和WordCount模拟

    最早接触大数据,常萦绕耳边的一个词「MapReduce」.它到底是什么,能做什么,原理又是什么?且听下文讲解. 是什么 MapReduce 即是一个编程模型,又是一个计算框架,它充分采用了分治的思想, ...

  9. 【SSH网上商城项目实战30】项目总结

      转自:https://blog.csdn.net/eson_15/article/details/51479994 0. 写在前面 项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了 ...

  10. PowerDesigner16使用方法

    网上下载一个破解版的PowerDesigner https://www.cnblogs.com/longshiyVip/p/4643871.html 1.新建一个Physical Data Model ...