? ? ? ?新人剛剛接觸android,最近由于項(xiàng)目需求,需要實(shí)現(xiàn)類似于QQ空間里的發(fā)說說功能,大家都知道說說能發(fā)本地圖片,對于剛剛?cè)肟拥男氯俗约簩?shí)現(xiàn)還是花點(diǎn)時間的,于是上網(wǎng)查了下參考了許多網(wǎng)上大神的思路,當(dāng)然實(shí)戰(zhàn)中還是碰到了很多問題,自己做了些修改,終于做出了一個基本功能的版本。放在這里權(quán)當(dāng)做個筆記,這里只實(shí)現(xiàn)了最簡單的功能,要用到實(shí)際還需要添加很多東西哈,這里只做了讀取并展示,上傳以后再加。這里都是自己新入安卓的探索過程,漏洞百出,不喜勿噴哈~
先放個效果圖吧


好了下面記錄自己的思路。
首先需要實(shí)現(xiàn)圖片的展示,這里用Gridview實(shí)現(xiàn),圖片寫死了每行放四張。。初始demo以后再優(yōu)化。防止圖片選擇過多無限往下占用屏幕影響體驗(yàn),Gridview最多放20張圖片,顯示兩行。下面是activity里Gridview的布局
??? android:id="@+id/gridview"
? ? android:layout_width="match_parent"
? ? android:layout_height="wrap_content"
? ? android:numColumns="4"
? ? />
然后再activity代碼里設(shè)置gridview的大小(xml里wrap_content實(shí)際只顯示一行,最簡單的思路是調(diào)整高度實(shí)現(xiàn)顯示行數(shù))
//設(shè)置gridview跟屏幕等寬,高度為兩個圖片的長度,這樣就顯示兩行
WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int widthSingle = (width-50)/4;
ViewGroup.LayoutParams lp = new LinearLayout.LayoutParams(width, widthSingle*2 + 20);
gridview.setLayoutParams(lp);
先寫Gridview的adapter
public class ItemAdapter extends BaseAdapter {
? ? private List<String> list = new ArrayList<String>();//圖片url列表
? ? private Context context;
? ? private static int MAX_SINGLE_LINE = 4;//每行顯示4張圖片
? ? public ItemAdapter (List<String> list,Context context){
? ? ? ? this.list = list;
? ? ? ? this.context = context;
? ? }
? ? @Override
? ? public int getCount() {
? ? ? ? return list.size();
? ? }
? ? @Override
? ? public Object getItem(int position) {
? ? ? ? return null;
? ? }
? ? @Override
? ? public long getItemId(int position) {
? ? ? ? return 0;
? ? }
? ? @Override
? ? public View getView(int position, View convertView, ViewGroup parent) {
? ? ? ? ViewHolder viewholder = null;
? ? ? ? if (convertView == null) {
? ? ? ? ? ? convertView = View.inflate(context, R.layout.layout_image_item, null);
? ? ? ? ? ? viewholder = new ViewHolder();
? ? ? ? ? ? viewholder.iamge = (ImageView) convertView.findViewById(R.id.photo);
? ? ? ? ? ? convertView.setTag(viewholder);
? ? ? ? } else {
? ? ? ? ? ? viewholder = (ViewHolder) convertView.getTag();
? ? ? ? }
? ? ? ? //設(shè)置圖片長寬為屏幕寬度四分之一
? ? ? ? WindowManager wm = (WindowManager) ActivityUtil.findActivity(context).getSystemService(Context.WINDOW_SERVICE);
? ? ? ? DisplayMetrics dm = new DisplayMetrics();
? ? ? ? wm.getDefaultDisplay().getMetrics(dm);
? ? ? ? int width = dm.widthPixels;
? ? ? ? int widthSingle = (width-MAX_SINGLE_LINE;
? ? ? ? LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(widthSingle, widthSingle);
? ? ? ? lp.setMargins(5, 0, 0, 0);
? ? ? ? if (list.get(position).equals("default")) {? //添加默認(rèn)圖片
? ? ? ? ? ? viewholder.iamge.setLayoutParams(lp);
? ? ? ? ? ? viewholder.iamge.setImageResource(R.mipmap.add_photo);
? ? ? ? }
? ? ? ? else {
? ? ? ? ? ? Bitmap loacalBitmap = LoadUrl(list.get(position));
? ? ? ? ? ? if (loacalBitmap != null) {
? ? ? ? ? ? ? ? viewholder.iamge.setLayoutParams(lp);
? ? ? ? ? ? ? ? viewholder.iamge.setImageBitmap(loacalBitmap);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return convertView;
? ? }
? ? //讀取圖片url
? ? public static Bitmap LoadUrl(String url) {
? ? ? ? try {
? ? ? ? ? ? FileInputStream fis = new FileInputStream(url);
? ? ? ? ? ? return BitmapFactory.decodeStream(fis);
? ? ? ? } catch (FileNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? return null;
? ? ? ? }
? ? }
? ? class ViewHolder {
? ? ? ? ImageView iamge;
? ? }
}
下面是activity里Gridview的布局
? android:id="@+id/gridview"
? ? android:layout_width="match_parent"
? ? android:layout_height="wrap_content"
? ? android:numColumns="4"
? ? />
然后再activity代碼里設(shè)置gridview,findViewById就省略了
private GridView gridview;
private ItemAdapter itemAdapter;
?private List<String> list = new ArrayList<String>();//存儲選中圖片的url
private final int MAX_PHOTO = 21;//最多20張圖
private static final int MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE = 1; private static final int MY_PERMISSIONS_READ_EXTERNAL_STORAGE = 2;
onCreate里
//?xml里設(shè)置wrap_content實(shí)際只顯示一行,最簡單的思路是調(diào)整高度實(shí)現(xiàn)顯示行數(shù)
//設(shè)置gridview跟屏幕等寬,高度為兩個圖片的長度,這樣就顯示兩行
WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int widthSingle = (width-50)/4;
ViewGroup.LayoutParams lp = new LinearLayout.LayoutParams(width, widthSingle*2 + 20);
gridview.setLayoutParams(lp);
//添加默認(rèn)圖片
list.add("default");
itemAdapter = new ItemAdapter(list,context);
gridview.setAdapter(photoAdapter);
然后設(shè)置監(jiān)聽,點(diǎn)擊默認(rèn)圖片進(jìn)入相冊選擇圖片,進(jìn)入相冊獲取圖片url的方法:
/**
* 進(jìn)入相冊
*/
private void JumpToDCIM(){
Intent intent =new Intent(Intent.ACTION_PICK,
? ? ? ? ? ? android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
? ? startActivityForResult(intent, 0);
}
選擇圖片后的回調(diào),獲取url
/**
? ? * 進(jìn)入相冊后選擇圖片的回調(diào)
? ? * @param requestCode
? ? * @param resultCode
? ? * @param data
? ? */
? ? @Override
? ? protected void onActivityResult(int requestCode, int resultCode, Intent data) {
? ? ? ? super.onActivityResult(requestCode, resultCode, data);
? ? ? ? if(data == null){
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (requestCode == 0) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? Uri originalUri = data.getData();
? ? ? ? ? ? ? ? ContentResolver testcr = getContentResolver();
? ? ? ? ? ? ? ? Cursor cursor = testcr.query(originalUri, new String[] { MediaStore.Images.Media.DATA }, null, null, null);
? ? ? ? ? ? ? ? if(infoList.size() == MAX_PHOTO){
? ? ? ? ? ? ? ? ? ? removeItem();
? ? ? ? ? ? ? ? ? ? refreshAdapter();
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (null == cur) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? removeItem();
? ? ? ? ? ? ? ? for ( cursor.moveToFirst(); ! cursor.isAfterLast(); cursor.moveToNext()) {
? ? ? ? ? ? ? ? ? ? int dataColumn =? curso.getColumnIndex(MediaStore.Images.Media.DATA);
? ? ? ? ? ? ? ? ? ? String image_path = cursor.getString(dataColumn);
? ? ? ? ? ? ? ? ? ? infoList.add(image_path);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? infoList.add("default");
? ? ? ? ? ? ? ? refreshAdapter();
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? System.out.println(e.getMessage());
? ? ? ? ? ? }
? ? ? ? }
? ? }
refreshAdapter方法:
/**
? ? * 刷新視圖
? ? */
? ? private void refreshAdapter(){
? ? ? ? if(infoList == null){
? ? ? ? ? ? infoList = new ArrayList<String>();
? ? ? ? }
? ? ? ? if(photoAdapter == null){
? ? ? ? ? ? photoAdapter = new PhotoAdapter(infoList,mContext);
? ? ? ? }
? ? ? ? if(infoList.size() == MAX_PIC){
? ? ? ? ? ? infoList.remove(infoList.size() - 1);
? ? ? ? }
? ? ? ? photoAdapter.notifyDataSetChanged();
? ? }
removeItem方法:
/**
* 達(dá)到最大圖片數(shù)刪除默認(rèn)圖片,不能添加
*/
private void removeItem() {
if(infoList.size() -1 !=MAX_PIC){
if(infoList.size() !=0){//刪除默認(rèn)圖片
? ? ? ? ? ? infoList.remove(infoList.size() -1);
? ? ? ? }
}
}
好了這樣獲取相冊里圖片url的方法寫好了,我們在Gridview的監(jiān)聽里判斷只要點(diǎn)擊的是默認(rèn)圖片就調(diào)用這個JumpToDCIM方法。
然后發(fā)現(xiàn)并不好使,選擇完圖片后啥也沒有增加。。。。。。
好吧繼續(xù)調(diào)試,打斷點(diǎn)試試,發(fā)現(xiàn)JumpToDCIM確實(shí)獲取到了圖片的url,問題出現(xiàn)在adapter的LoadUrl(String url)方法里,讀取url時報了permission denied異常。上網(wǎng)查了下這是什么東東,發(fā)現(xiàn)是沒有讀取權(quán)限,好吧那就添加權(quán)限。
我們在進(jìn)入相冊之前先設(shè)置讀寫權(quán)限,在AndroidManifest.xml里添加權(quán)限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
實(shí)戰(zhàn)中發(fā)現(xiàn)Android6.0以后AndroidManifest.xml里的設(shè)置并不管用,坑。。。那就寫個方法申請權(quán)限好了。
先寫檢查是否有權(quán)限的方法:
public static boolean checkPermission(Context context, String permissionStr){
? ? ? ? boolean result = true;
? ? ? ? if(Build.VERSION.SDK_INT >= 23){
? ? ? ? ? ? result = (context.checkSelfPermission(permissionStr) == PackageManager.PERMISSION_GRANTED);
? ? ? ? }
? ? ? ? else{
? ? ? ? ? ? result = (PermissionChecker.checkSelfPermission(context,permissionStr) == PackageManager.PERMISSION_GRANTED);
? ? ? ? }
? ? ? ? return result;
? ? }
然后是請求權(quán)限的方法,調(diào)用該方法后系統(tǒng)會彈出彈窗確認(rèn):
@RequiresApi(api = 23)
? ? public static void requestPermission(Activity activity, String[] permissionStrs, int requestCode){
? ? ? ? activity.requestPermissions(permissionStrs,requestCode);
? ? }
請求權(quán)限的回調(diào),這里需要開頭對permissions,grantResults進(jìn)行非空判斷,不然請求權(quán)限的彈窗出現(xiàn)時在用戶選擇之前就會回調(diào),permissions,grantResults此時都為空就會崩潰。
@Override
? ? public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
? ? ? ? if( permissions.length > 0 && grantResults.length > 0
? ? ? ? ? ? if (requestCode == MY_PERMISSIONS_READ_EXTERNAL_STORAGE) {
? ? ? ? ? ? ? ? if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? ? ? JumpToDCIM();
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // Permission Denied
? ? ? ? ? ? ? ? ? ? Toast.makeText(mContext, "用戶拒絕添加讀取權(quán)限", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (requestCode == MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE) {
? ? ? ? ? ? ? ? if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? ? ? JumpToDCIM ();
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // Permission Denied
? ? ? ? ? ? ? ? ? ? Toast.makeText(mContext, "用戶拒絕添加寫入權(quán)限", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? super.onRequestPermissionsResult(requestCode, permissions, grantResults);
? ? }
好了現(xiàn)在可以在Gridview里添加監(jiān)聽讀取相冊了,代碼如下。
/**
? ? ? ? * 如果是默認(rèn)圖片則點(diǎn)擊進(jìn)入相冊添加,進(jìn)入前判斷是否有讀寫權(quán)限,沒有的話申請權(quán)限(Android 6.0/API 23以上時AndroidManifest里添加權(quán)限無效需要申請權(quán)限)
? ? ? ? */
? ? ? ? gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
? ? ? ? ? ? ? ? if(infoList.get(position).equals("default")){
? ? ? ? ? ? ? ? ? ? if(checkPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE) && checkPermission(mContext,Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
? ? ? ? ? ? ? ? ? ? ? ? JumpToDCIM ();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else {
? ? ? ? ? ? ? ? ? ? ? ? if(Build.VERSION.SDK_INT >= 23) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? requestPermission(AddDiaryActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_READ_EXTERNAL_STORAGE);
? ? ? ? ? ? ? ? ? ? ? ? ? ? requestPermission(AddDiaryActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
OK,一個最最簡單功能的demo就實(shí)現(xiàn)了,收工。