Android 實(shí)現(xiàn)類似于QQ空間選擇并展示本地圖片

? ? ? ?新人剛剛接觸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)了,收工。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容