首先 点击头像的时候 会弹出PopupWindow 所以写好头像的点击事件 之后 去写一个pop的类
public class Pop implements View.OnClickListener{
private Context context = null;
private PopupWindow popupWindow = null;
private OnSelectPictureListener listener = null;
public Pop(Context context, View popview, OnSelectPictureListener listener) {
this.context = context;
this.listener = listener;
View view = LayoutInflater.from(context).inflate(R.layout.popwindow_layout, null);
initView(view, popview);
}
private void initView(View view, View popview) {
popupWindow = new PopupWindow(popview,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
popupWindow.setContentView(view);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
popupWindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);//show()
view.findViewById(R.id.popup_select_take_photo).setOnClickListener(this);
view.findViewById(R.id.popup_select_take_picture).setOnClickListener(this);
view.findViewById(R.id.popup_select_take_cancel).setOnClickListener(this);
}
@Override
public void onClick(View view) {
int i = view.getId();
if (i == R.id.popup_select_take_photo) {
listener.onTakePhoto();
} else if (i == R.id.popup_select_take_picture) {
listener.onSelectPicture();
} else if (i == R.id.popup_select_take_cancel) {
listener.onCancel();
}
//点击完了之后隐藏
popupWindow.dismiss();
}
//点击接口
public interface OnSelectPictureListener {
/**
* 拍摄
*/
void onTakePhoto();
/**
* 从相册选择
*/
void onSelectPicture();
/**
* 取消
*/
void onCancel();
}
}
上面类中所用到的布局文件
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/share_main_line"
android:layout_margin="10dp"
android:background="@drawable/pop_bag"
android:orientation="vertical">
<TextView
android:id="@+id/popup_select_take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="拍照"
android:textColor="#333333"
android:textSize="16sp" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_above="@+id/popup_select_take_cancel"
android:background="#ebebeb" />
<TextView
android:id="@+id/popup_select_take_picture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="从手机相册选择"
android:textColor="#333333"
android:textSize="16sp" />
</LinearLayout>
<View
android:id="@+id/share_main_line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="19dp"
android:layout_marginRight="19dp"
android:layout_above="@+id/popup_select_take_cancel"
android:background="#ebebeb" />
<TextView
android:id="@+id/popup_select_take_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/pop_bag"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center"
android:padding="10dp"
android:text="取消"
android:textColor="#333"
android:textSize="16sp" />
</RelativeLayout>
在这个布局中又用到了 一个自定义shape和一个半透明的颜色
#7f000000 半透明颜色
<shape xmlns:android="http://schemas.android.com/apk/res/android"
>
<solid android:color="#ffffff"
/>
<corners android:radius="10dp"/>
</shape>
pop 创建完了之后 继续写头像的点击事件
//弹出PopupWindow
private void tanpop() {
//先去创建一个pop的工具类
//new 调用pop工具类 括号里传上下文和本页面布局整体的id new 接口提示
new Pop(context, chage_pop, new Pop.OnSelectPictureListener() {
@Override
public void onTakePhoto() {
//new 意图跳转相机 mediastore .相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//意图传值mediastor .ex ,uri.fromfile括号new文件传获取系统路径传文件名
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), pic)));
//回调方法跳转相机强转本页面0 回调方法写在Activity 调用方法生成过来
((LoginLastActivity) context).startActivityForResult(intent, 1);
}
@Override
public void onSelectPicture() {
//new 意图跳转相册
Intent intent = new Intent(Intent.ACTION_PICK, null);
//意图设置dataAnd Type mediastore images.media .ex ,imgae/*通配符
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
//带值跳转1
((LoginLastActivity) context).startActivityForResult(intent, 0);
}
@Override
public void onCancel() {
//取消方法不用写
}
});
}
pop的类中有三个接口 分别是相机相册取消 上面 已经写好了实现接口
和activity的带值跳转 下面该做的是 写activity的回调方法 因为这里用的是themvp 所以需要去该页面的Activity中写onActivityResult
//回调方法
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//判读requestcode
switch (requestCode){
case 0:
//当时0的时候调用方法生成到persenter 传resultcode 和data相机回调
delegate.onCode0(resultCode,data);
break;
case 1:
//当时0的时候调用方法生成到persenter 传resultcode 相册回调
delegate.onCode1(resultCode);
break;
case 2:
//当时0的时候调用方法生成到persenter 传rdata 裁剪回调
delegate.onCode2(data);
break;
}
}
persenter里的具体实现方法
//生成过来的方法相机
public void onCode0(int resultCode, Intent data) {
//判断code==RESULT _OK
if (resultCode == RESULT_OK) {
//调用裁剪的方法
cropPhoto(data.getData());
}
}
// 相册回调
public void onCode1(int resultCode) {
//判断code==RESULT _OK
if (resultCode == RESULT_OK) {
//new 文件
File file = new File(Environment.getExternalStorageDirectory() + "/head.png");
//调用裁剪方法传file URI 调用filefromfile
cropPhoto(Uri.fromFile(file));
}
}
//裁剪回调方法
public void onCode2(Intent data) {
// Toast.makeText(context,"哈哈"+data,Toast.LENGTH_SHORT).show();
//先判断data非空
if (data != null) {
//data 获取extras 返回值
Bundle extras = data.getExtras();
//判断等于空直接返回
if (extras == null) {
return;
}
//extras .获取p传引号data返回值head 提上去Bitmap类型
head = extras.getParcelable("data");
//判断判断head非空
if (head != null) {
//给头像设置imagebitmap 传head
// last_tou.setImageBitmap(head);
// //上面封装的固定路径+引号/+pic图片名
String fileNname = path + "/" + pic;
// 调用储存sd卡的方法 传head
setPicToView(head);
//调用ok上传 传个filename
Log.i("上传的时候",fileNname);
uploadImage(fileNname);
//重新保存头像的方法
setIcon();
}
}
}
在回调具体方法里 又用到了 裁剪 、储存sd卡 、okhttp上传头像 、重新保存头像的方法
裁剪
//裁剪回调方法
public void onCode2(Intent data) {
// Toast.makeText(context,"哈哈"+data,Toast.LENGTH_SHORT).show();
//先判断data非空
if (data != null) {
//data 获取extras 返回值
Bundle extras = data.getExtras();
//判断等于空直接返回
if (extras == null) {
return;
}
//extras .获取p传引号data返回值head 提上去Bitmap类型
head = extras.getParcelable("data");
//判断判断head非空
if (head != null) {
//给头像设置imagebitmap 传head
// last_tou.setImageBitmap(head);
// //上面封装的固定路径+引号/+pic图片名
String fileNname = path + "/" + pic;
// 调用储存sd卡的方法 传head
setPicToView(head);
//调用ok上传 传个filename
Log.i("上传的时候",fileNname);
uploadImage(fileNname);
//重新保存头像的方法
setIcon();
}
}
}
储存sd卡
//储存sd卡的方法
private void setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
return;
}
FileOutputStream b = null;
File file = new File(path);
file.mkdirs();// 创建文件夹
String fileName = path + "/head.png";//图片名字
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把数据写入文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
//关闭流
b.flush();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
okhttp上传头像
如果需要换网址 记得在new Request.Builder()的里面更换网址
//okhttp上传头像
private void uploadImage(String path) {
MediaType mediaType = MediaType.parse("multipart/form-data; charset=utf-8");
OkHttpClient mOkHttpClent = new OkHttpClient();
File file = new File(path);
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(mediaType)
.addFormDataPart("file", pic,
RequestBody.create(MediaType.parse("image/png"), file))
.addFormDataPart("uid", uid);
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url("网址")
.post(requestBody)
.build();
Call call = mOkHttpClent.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
((LoginLastActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("TAG", e.getMessage());
Toast.makeText(context, "失败", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
((LoginLastActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "更换成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
重新保存头像的方法
这个方法 就是 又重新请求了一次服务端 用来更新本地sp中缓存的头像
顺便给本页面的头像控件赋值
//重新保存头像的方法
private void setIcon() {
//传一个uid就可以
HashMap<String, String> map = new HashMap<>();
map.put("uid", uid);
RetrofitUtils.getRetrofitUtils().get(url, map).result(new RetrofitUtils.RetrofitListener() {
@Override
public void success(String s) {
//解析读取出来的s
UserBean userBean = new Gson().fromJson(s, UserBean.class);
//获取头像
//储存到sp里面
//往sp里存东西 昵称写在下面判断和icon to字符串 或者加个空字符串
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
sp.edit().putString("icon",userBean.getData().getIcon()).commit();
Log.i("储存的图",userBean.getData().getIcon());
//重新给图片赋值
String s1 = path + "/" + pic;
last_tou.setImageBitmap(BitmapFactory.decodeFile(s1));
}
@Override
public void fail() {
//网络错误
Toast.makeText(context,"网络竟然崩溃了",Toast.LENGTH_SHORT).show();
}
});
}
在以上的方法中 用到的几个封装变量
private String pic = "head.png";
private Bitmap head;
//封装一个固定路径
private static String path = "/sdcard/myHead/";//sd路径
登陆成功的uid 在this.uid=uid在Activity onResume方法里面更新数据生成在persenter的方法里获取uid提上去
private String uid;
//获取用户信息的接口
private String url = "网址";