一般都是有圆形显示头像的,这里我自定义了一个ImageView,页面很干净但是看着很上档次吧!
点击头像从底部弹出一个对话框,提示用户头像来自相机或者相册,这都是常规流程。
上传完成后默认的“程序员头像”换成了萌妹子
模仿QQ空间发动态的布局随意捏造一个界面出来
点击添加图片从底部弹出一个对话框,提示用户图片来自相机或者相册,这也都是常规流程。
上传过程中,有可能图片很大,显示一个进度圈(其实头像上传也有,只是文件小,还没显示就上传完成了)
上传完成后把刚才的照片亮出来显示到按钮的地方,当然大家根据需要还可以自己扩展(比如长按抖动出现删除、继续添加N张等等)。这里上边的按钮是头像的点击事件,弹出底部的头像选择框,下边的按钮跳到下个页面,进行原图上传。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.avatarImg:
// 更换头像点击事件
menuWindow =
new
SelectPicPopupWindow(mContext, itemsOnClick);
menuWindow.showAtLocation(findViewById(R.id.mainLayout),
Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,
0
,
0
);
break
;
case
R.id.loginBtn:
//登录按钮跳转事件
startActivity(
new
Intent(mContext, UploadActivity.
class
));
break
;
default
:
break
;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//为弹出窗口实现监听类
private
OnClickListener itemsOnClick =
new
OnClickListener() {
@Override
public
void
onClick(View v) {
menuWindow.dismiss();
switch
(v.getId()) {
// 拍照
case
R.id.takePhotoBtn:
Intent takeIntent =
new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//下面这句指定调用相机拍照后的照片存储的路径
takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(
new
File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)));
startActivityForResult(takeIntent, REQUESTCODE_TAKE);
break
;
// 相册选择图片
case
R.id.pickPhotoBtn:
Intent pickIntent =
new
Intent(Intent.ACTION_PICK,
null
);
// 如果朋友们要限制上传到服务器的图片类型时可以直接写如:image/jpeg 、 image/png等的类型
pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image/*);
startActivityForResult(pickIntent, REQUESTCODE_PICK);
break
;
default
:
break
;
}
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Override
public
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
switch
(requestCode) {
case
REQUESTCODE_PICK:
// 直接从相册获取
try
{
startPhotoZoom(data.getData());
}
catch
(NullPointerException e) {
e.printStackTrace();
// 用户点击取消操作
}
break
;
case
REQUESTCODE_TAKE:
// 调用相机拍照
File temp =
new
File(Environment.getExternalStorageDirectory() + / + IMAGE_FILE_NAME);
startPhotoZoom(Uri.fromFile(temp));
break
;
case
REQUESTCODE_CUTTING:
// 取得裁剪后的图片
if
(data !=
null
) {
setPicToView(data);
}
break
;
}
super
.onActivityResult(requestCode, resultCode, data);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/**
* 裁剪图片方法实现
* @param uri
*/
public
void
startPhotoZoom(Uri uri) {
Intent intent =
new
Intent(com.android.camera.action.CROP);
intent.setDataAndType(uri, image
/*);
// crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
intent.putExtra(crop, true);
// aspectX aspectY 是宽高的比例
intent.putExtra(aspectX, 1);
intent.putExtra(aspectY, 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra(outputX, 300);
intent.putExtra(outputY, 300);
intent.putExtra(return-data, true);
startActivityForResult(intent, REQUESTCODE_CUTTING);
}
/**
* 保存裁剪之后的图片数据
* @param picdata
*/
private
void
setPicToView(Intent picdata) {
Bundle extras = picdata.getExtras();
if
(extras !=
null
) {
// 取得SDCard图片路径做显示
Bitmap photo = extras.getParcelable(data);
Drawable drawable =
new
BitmapDrawable(
null
, photo);
urlpath = FileUtil.saveFile(mContext, temphead.jpg, photo);
avatarImg.setImageDrawable(drawable);
// 新线程后台上传服务端
pd = ProgressDialog.show(mContext,
null
, 正在上传图片,请稍候...);
new
Thread(uploadImageRunnable).start();
}
}
/**
* 使用HttpUrlConnection模拟post表单进行文件
* 上传平时很少使用,比较麻烦
* 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。
*/
Runnable uploadImageRunnable =
new
Runnable() {
@Override
public
void
run() {
if
(TextUtils.isEmpty(imgUrl)){
Toast.makeText(mContext, 还没有设置上传服务器的路径!, Toast.LENGTH_SHORT).show();
return
;
}
Map
Map
try
{
// 创建一个URL对象
URL url =
new
URL(imgUrl);
textParams =
new
HashMap
fileparams =
new
HashMap
// 要上传的图片文件
File file =
new
File(urlpath);
fileparams.put(image, file);
// 利用HttpURLConnection对象从网络中获取网页数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)
conn.setConnectTimeout(
5000
);
// 设置允许输出(发送POST请求必须设置允许输出)
conn.setDoOutput(
true
);
// 设置使用POST的方式发送
conn.setRequestMethod(POST);
// 设置不使用缓存(容易出现问题)
conn.setUseCaches(
false
);
conn.setRequestProperty(Charset, UTF-
8
);
//设置编码
// 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头
conn.setRequestProperty(ser-Agent, Fiddler);
// 设置contentType
conn.setRequestProperty(Content-Type, multipart/form-data; boundary= + NetUtil.BOUNDARY);
OutputStream os = conn.getOutputStream();
DataOutputStream ds =
new
DataOutputStream(os);
NetUtil.writeStringParams(textParams, ds);
NetUtil.writeFileParams(fileparams, ds);
NetUtil.paramsEnd(ds);
// 对文件流操作完,要记得及时关闭
os.close();
// 服务器返回的响应吗
int
code = conn.getResponseCode();
// 从Internet获取网页,发送请求,将网页以流的形式读回来
// 对响应码进行判断
if
(code ==
200
) {
// 返回的响应码200,是成功
// 得到网络返回的输入流
InputStream is = conn.getInputStream();
resultStr = NetUtil.readString(is);
}
else
{
Toast.makeText(mContext, 请求URL失败!, Toast.LENGTH_SHORT).show();
}
}
catch
(Exception e) {
e.printStackTrace();
}
handler.sendEmptyMessage(
0
);
// 执行耗时的方法之后发送消给handler
}
};
Handler handler =
new
Handler(
new
Handler.Callback() {
@Override
public
boolean
handleMessage(Message msg) {
switch
(msg.what) {
case
0
:
pd.dismiss();
try
{
// 返回数据示例,根据需求和后台数据灵活处理
// {status:1,statusMessage:上传成功,imageUrl:http://120.24.219.49/726287_temphead.jpg}
JSONObject jsonObject =
new
JSONObject(resultStr);
// 服务端以字符串“1”作为操作成功标记
if
(jsonObject.optString(status).equals(
1
)) {
BitmapFactory.Options option =
new
BitmapFactory.Options();
// 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图,3为三分之一
option.inSampleSize =
1
;
// 服务端返回的JsonObject对象中提取到图片的网络URL路径
String imageUrl = jsonObject.optString(imageUrl);
Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(mContext, jsonObject.optString(statusMessage), Toast.LENGTH_SHORT).show();
}
}
catch
(JSONException e) {
e.printStackTrace();
}
break
;
default
:
break
;
}
return
false
;
}
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//为弹出窗口实现监听类
private
OnClickListener itemsOnClick =
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// 隐藏弹出窗口
menuWindow.dismiss();
switch
(v.getId()) {
case
R.id.takePhotoBtn:
// 拍照
takePhoto();
break
;
case
R.id.pickPhotoBtn:
// 相册选择图片
pickPhoto();
break
;
case
R.id.cancelBtn:
// 取消
break
;
default
:
break
;
}
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/**
* 拍照获取图片
*/
private
void
takePhoto() {
// 执行拍照前,应该先判断SD卡是否存在
String SDState = Environment.getExternalStorageState();
if
(SDState.equals(Environment.MEDIA_MOUNTED)) {
Intent intent =
new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/***
* 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的
* 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图
* 如果不使用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰
*/
ContentValues values =
new
ContentValues();
photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
}
else
{
Toast.makeText(
this
, 内存卡不存在, Toast.LENGTH_LONG).show();
}
}
/***
* 从相册中取图片
*/
private
void
pickPhoto() {
Intent intent =
new
Intent();
// 如果要限制上传到服务器的图片类型时可以直接写如:image/jpeg 、 image/png等的类型
intent.setType(image/*);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Override
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
// 点击取消按钮
if
(resultCode == RESULT_CANCELED){
return
;
}
// 可以使用同一个方法,这里分开写为了防止以后扩展不同的需求
switch
(requestCode) {
case
SELECT_PIC_BY_PICK_PHOTO:
// 如果是直接从相册获取
doPhoto(requestCode, data);
break
;
case
SELECT_PIC_BY_TACK_PHOTO:
// 如果是调用相机拍照时
doPhoto(requestCode, data);
break
;
}
super
.onActivityResult(requestCode, resultCode, data);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/**
* 选择图片后,获取图片的路径
*
* @param requestCode
* @param data
*/
private
void
doPhoto(
int
requestCode, Intent data) {
// 从相册取图片,有些手机有异常情况,请注意
if
(requestCode == SELECT_PIC_BY_PICK_PHOTO) {
if
(data ==
null
) {
Toast.makeText(
this
, 选择图片文件出错, Toast.LENGTH_LONG).show();
return
;
}
photoUri = data.getData();
if
(photoUri ==
null
) {
Toast.makeText(
this
, 选择图片文件出错, Toast.LENGTH_LONG).show();
return
;
}
}
String[] pojo = { MediaColumns.DATA };
// The method managedQuery() from the type Activity is deprecated
//Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
Cursor cursor = mContext.getContentResolver().query(photoUri, pojo,
null
,
null
,
null
);
if
(cursor !=
null
) {
int
columnIndex = cursor.getColumnIndexOrThrow(pojo[
0
]);
cursor.moveToFirst();
picPath = cursor.getString(columnIndex);
// 4.0以上的版本会自动关闭 (4.0--14;; 4.0.3--15)
if
(Integer.parseInt(Build.VERSION.SDK) <
14
) {
cursor.close();
}
}
// 如果图片符合要求将其上传到服务器
if
(picPath !=
null
&& ( picPath.endsWith(.png) ||
picPath.endsWith(.PNG) ||
picPath.endsWith(.jpg) ||
picPath.endsWith(.JPG))) {
BitmapFactory.Options option =
new
BitmapFactory.Options();
// 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图
option.inSampleSize =
1
;
// 根据图片的SDCard路径读出Bitmap
Bitmap bm = BitmapFactory.decodeFile(picPath, option);
// 显示在图片控件上
picImg.setImageBitmap(bm);
pd = ProgressDialog.show(mContext,
null
, 正在上传图片,请稍候...);
new
Thread(uploadImageRunnable).start();
}
else
{
Toast.makeText(
this
, 选择图片文件不正确, Toast.LENGTH_LONG).show();
}
}
/**
* 使用HttpUrlConnection模拟post表单进行文件
* 上传平时很少使用,比较麻烦
* 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。
*/
Runnable uploadImageRunnable =
new
Runnable() {
@Override
public
void
run() {
if
(TextUtils.isEmpty(imgUrl)){
Toast.makeText(mContext, 还没有设置上传服务器的路径!, Toast.LENGTH_SHORT).show();
return
;
}
Map
Map
try
{
// 创建一个URL对象
URL url =
new
URL(imgUrl);
textParams =
new
HashMap
fileparams =
new
HashMap
// 要上传的图片文件
File file =
new
File(picPath);
fileparams.put(image, file);
// 利用HttpURLConnection对象从网络中获取网页数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)
conn.setConnectTimeout(
5000
);
// 设置允许输出(发送POST请求必须设置允许输出)
conn.setDoOutput(
true
);
// 设置使用POST的方式发送
conn.setRequestMethod(POST);
// 设置不使用缓存(容易出现问题)
conn.setUseCaches(
false
);
// 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头
conn.setRequestProperty(ser-Agent, Fiddler);
// 设置contentType
conn.setRequestProperty(Content-Type, multipart/form-data; boundary= + NetUtil.BOUNDARY);
OutputStream os = conn.getOutputStream();
DataOutputStream ds =
new
DataOutputStream(os);
NetUtil.writeStringParams(textParams, ds);
NetUtil.writeFileParams(fileparams, ds);
NetUtil.paramsEnd(ds);
// 对文件流操作完,要记得及时关闭
os.close();
// 服务器返回的响应吗
int
code = conn.getResponseCode();
// 从Internet获取网页,发送请求,将网页以流的形式读回来
// 对响应码进行判断
if
(code ==
200
) {
// 返回的响应码200,是成功
// 得到网络返回的输入流
InputStream is = conn.getInputStream();
resultStr = NetUtil.readString(is);
}
else
{
Toast.makeText(mContext, 请求URL失败!, Toast.LENGTH_SHORT).show();
}
}
catch
(Exception e) {
e.printStackTrace();
}
handler.sendEmptyMessage(
0
);
// 执行耗时的方法之后发送消给handler
}
};
Handler handler =
new
Handler(
new
Handler.Callback() {
@Override
public
boolean
handleMessage(Message msg) {
switch
(msg.what) {
case
0
:
pd.dismiss();
try
{
JSONObject jsonObject =
new
JSONObject(resultStr);
// 服务端以字符串“1”作为操作成功标记
if
(jsonObject.optString(status).equals(
1
)) {
// 用于拼接发布说说时用到的图片路径
// 服务端返回的JsonObject对象中提取到图片的网络URL路径
String imageUrl = jsonObject.optString(imageUrl);
// 获取缓存中的图片路径
Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(mContext, jsonObject.optString(statusMessage), Toast.LENGTH_SHORT).show();
}
}
catch
(JSONException e) {
e.printStackTrace();
}
break
;
default
:
break
;
}
return
false
;
}
});
|