先看一下效果圖:
(一)頭像裁切、上傳服務器(效果圖)
一般都是有圓形顯示頭像的,這裏我自定義了一個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<string,
string= "" >
textParams = new
HashMap<string, string= "" >(); Map<string,
file= "" >
fileparams = new
HashMap<string, file= "" >(); try
{ //
創建一個URL對象 URL
url = new
URL(imgUrl); textParams
= new
HashMap<string, string= "" >(); fileparams
= new
HashMap<string, file= "" >(); //
要上傳的圖片文件 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 ; } });</string,></string,></string,></string,></string,></string,> |
(二)普通圖片上傳服務器(代碼)
直接從這裏開始,和頭像那裏基本沒什麼區別,我把拍照什麼的單獨抽出了方法,思路更清晰
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<string,
string= "" >
textParams = new
HashMap<string, string= "" >(); Map<string,
file= "" >
fileparams = new
HashMap<string, file= "" >(); try
{ //
創建一個URL對象 URL
url = new
URL(imgUrl); textParams
= new
HashMap<string, string= "" >(); fileparams
= new
HashMap<string, file= "" >(); //
要上傳的圖片文件 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 ; } });</string,></string,></string,></string,></string,></string,>
歡迎加入技術學習羣:364595326
|