在Android開發中BaseAdapter經常使用,一般常用於列表中。接下來我就以拍照功能來介紹一下他的簡單的使用方法。
拍照功能常常會出現不止拍一張的情況,連續拍多張放在一個列表里,這種情況時最常見的,也是最使用的。
首先我們建一個Activity頁面命名為CamerDemo,然后在頁面中添加操作組件。要做一個照片的列表,這里用GridView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".CamerDemo" android:background="@color/white" android:orientation="vertical"> <GridView android:id="@+id/grid_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:numColumns="4" /> </LinearLayout>
由於拍一張照片我就要動態添加一個imageView,然后放在GridView列表中去,所以我要建一個盛放照片的模具。所以添加一個頁面為Camer_Item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="70dp" android:layout_height="70dp" android:background="#00F8F8FF"> <Button android:id="@+id/bt_del" android:layout_width="20dp" android:layout_height="20dp" android:layout_alignParentRight="true" android:background="@drawable/chahao" /> //這個時上圖顯示的❌好,就不放了,自己找個圖就行。 <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp" android:background="@color/white"> <ImageView android:id="@+id/iv_image" android:layout_width="60dp" android:layout_height="60dp" android:gravity="center" android:scaleType="centerCrop" /> </RelativeLayout> </RelativeLayout>
接下來就時調用相機拍照了:
首先要在AndroidManifest.xml添加網絡權限:
調用相機權限:
<uses-permission android:name="android.permission.CAMERA" />
往服務器上上傳圖片,需要網絡權限:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>`
然后就是Activity頁面代碼了:
動態獲取相機權限,並調用相機拍照
public void openCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.addCategory(Intent.CATEGORY_DEFAULT); uri = getImageUri(); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, 1); } public Uri getImageUri() { file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".png"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } String path = file.getPath(); filepath=path; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { uri = Uri.fromFile(file); } else { //兼容android7.0 使用共享文件的形式 ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DATA, path); uri = this.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); } return uri; } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); //相機拍完照片后的回調 } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(permissions[0].equals(android.Manifest.permission.CAMERA)){ if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ Toast.makeText(CamerDemo.this,"已授權",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "授權失敗", Toast.LENGTH_SHORT).show(); } } } /** * 判斷是否授權開啟攝像機功能 */ private void isOpenPhoto(){ if(Build.VERSION.SDK_INT>=23){ ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); int permission = ContextCompat.checkSelfPermission(CamerDemo.this.getApplicationContext(), android.Manifest.permission.CAMERA); if(permission== PackageManager.PERMISSION_GRANTED){ //如果有了相機的權限就調用相機 }else { AlertDialog.Builder builder=new AlertDialog.Builder(CamerDemo.this); builder.setTitle("提示"); builder.setMessage("是否開啟相機權限"); builder.setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //去請求相機權限 ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); } }); builder.setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(CamerDemo.this, "您拒絕了開啟相機權限", Toast.LENGTH_SHORT).show(); } }); builder.show(); } } }
相機拍完后要顯示在app上,最簡單的方法就是直接在頁面上建一個Imageview,把照片放到Imageview中,但是這樣很明顯有點弊端,那就是在實際應用中,拍多少照片時不固定的,所以之惡能動態生成顯示照片。
所以我們要定義一個 GridViewAdapter 繼承BaseAdapter然后通過適配器完成。
public class GridViewAdapter extends BaseAdapter { private Context context; private List<CamerIcon> list; LayoutInflater layoutInflater; private ImageView mImageView; private Button delbtn; public GridViewAdapter(Context context, List<CamerIcon> list) { this.context = context; this.list = list; layoutInflater = LayoutInflater.from(context); } //添加一個元素 public void add(CamerIcon data) { if (list == null) { list = new ArrayList<>(); } list.add(data); notifyDataSetChanged(); } //往特定位置,添加一個元素 public void add(int position, CamerIcon data) { if (list == null) { list= new ArrayList<>(); } list.add(position, data); notifyDataSetChanged(); } //移除當前數據的組件 public void remove(CamerIcon data) { if (list != null) { list.remove(data); } notifyDataSetChanged(); } //移除當前位置的組件 public void remove(int position) { if (list != null) { list.remove(position); } notifyDataSetChanged(); } public void clear() { if (list != null) { list.clear(); } notifyDataSetChanged(); } @Override public int getCount() { return list.size()+1;//注意此處 } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { convertView = layoutInflater.inflate(R.layout.camer_item, null); mImageView = convertView.findViewById(R.id.iv_image); delbtn=convertView.findViewById(R.id.bt_del); if (position < list.size()) { mImageView.setImageURI(list.get(position).getUri()); delbtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { remove(position); } }); mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LayoutInflater inflater = LayoutInflater.from(CamerDemo.this); View imgEntryView = inflater.inflate(R.layout.largeicon, null); // 加載自定義的布局文件 final AlertDialog dialog = new AlertDialog.Builder(CamerDemo.this).create(); ImageView img = imgEntryView.findViewById(R.id.large_image); Bitmap bitmap = ((BitmapDrawable) mImageView.getDrawable()).getBitmap(); img.setImageBitmap(bitmap); dialog.setView(imgEntryView); // 自定義dialog dialog.show(); // 點擊布局文件(也可以理解為點擊大圖)后關閉dialog,這里的dialog不需要按鈕 imgEntryView.setOnClickListener(new View.OnClickListener() { public void onClick(View paramView) { dialog.cancel(); } }); } }); }else{ delbtn.setVisibility(View.GONE); mImageView.setBackgroundResource(R.drawable.jiahao);//最后一個顯示加號圖片 mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhrenli),"")); openCamera(); } }); } return convertView; } }
largeicon是查看大圖的布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/black" xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:layout_height="wrap_content" android:id="@+id/large_image" android:adjustViewBounds="true" android:layout_width="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true"> </ImageView> </RelativeLayout>
適配的模型:
package com.example.appview;
import android.net.Uri;
public class CamerIcon {
private Uri uri;
private String path;//這個是照片拍照完成后存放在本地的圖片路徑
public CamerIcon() {
}
public CamerIcon( Uri uri, String path) {
this.uri=uri;
this.path=path;
}
public String getPath() {
return path;
}
public Uri getUri() {
return uri;
}
public void setPath(String path) {
this.path = path;
}
public void setUri(Uri uri) {
this.uri = uri;
}
}
完整代碼:
package com.example.appview; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.app.Dialog; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.Toast; import java.io.File; import java.util.ArrayList; import java.util.List; public class CamerDemo extends AppCompatActivity { private List<CamerIcon> mDatas; private GridView mGridView; // private GridViewAdapter adapter; private File file= null; private Uri uri; private String filepath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camer_demo); mGridView=findViewById(R.id.grid_photo); isOpenPhoto(); initDatas(); adapter=new GridViewAdapter(CamerDemo.this,mDatas); mGridView.setAdapter(adapter); } private void initDatas() { mDatas=new ArrayList<>(); //mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); } /** * 得到資源文件中圖片的Uri * @param context 上下文對象 * @param id 資源id * @return Uri */ public Uri getUriFromDrawableRes(Context context, int id) { Resources resources = context.getResources(); String path = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + resources.getResourcePackageName(id) + "/" + resources.getResourceTypeName(id) + "/" + resources.getResourceEntryName(id); return Uri.parse(path); } public void openCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.addCategory(Intent.CATEGORY_DEFAULT); uri = getImageUri(); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, 1); } public Uri getImageUri() { file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".png"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } String path = file.getPath(); filepath=path; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { uri = Uri.fromFile(file); } else { //兼容android7.0 使用共享文件的形式 ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DATA, path); uri = this.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); } return uri; } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==1){ adapter.add(new CamerIcon(uri,"")); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(permissions[0].equals(android.Manifest.permission.CAMERA)){ if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ Toast.makeText(CamerDemo.this,"已授權",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "授權失敗", Toast.LENGTH_SHORT).show(); } } } /** * 判斷是否授權開啟攝像機功能 */ private void isOpenPhoto(){ if(Build.VERSION.SDK_INT>=23){ ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); int permission = ContextCompat.checkSelfPermission(CamerDemo.this.getApplicationContext(), android.Manifest.permission.CAMERA); if(permission== PackageManager.PERMISSION_GRANTED){ //如果有了相機的權限就調用相機 }else { AlertDialog.Builder builder=new AlertDialog.Builder(CamerDemo.this); builder.setTitle("提示"); builder.setMessage("是否開啟相機權限"); builder.setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //去請求相機權限 ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); } }); builder.setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(CamerDemo.this, "您拒絕了開啟相機權限", Toast.LENGTH_SHORT).show(); } }); builder.show(); } } }
public class GridViewAdapter extends BaseAdapter {
private Context context;
private List<CamerIcon> list;
LayoutInflater layoutInflater;
private ImageView mImageView;
private Button delbtn;
public GridViewAdapter(Context context, List<CamerIcon> list) {
this.context = context;
this.list = list;
layoutInflater = LayoutInflater.from(context);
}
//添加一個元素
public void add(CamerIcon data) {
if (list == null) {
list = new ArrayList<>();
}
list.add(data);
notifyDataSetChanged();
}
//往特定位置,添加一個元素
public void add(int position, CamerIcon data) {
if (list == null) {
list= new ArrayList<>();
}
list.add(position, data);
notifyDataSetChanged();
}
//移除當前數據的組件
public void remove(CamerIcon data) {
if (list != null) {
list.remove(data);
}
notifyDataSetChanged();
}
//移除當前位置的組件
public void remove(int position) {
if (list != null) {
list.remove(position);
}
notifyDataSetChanged();
}
public void clear() {
if (list != null) {
list.clear();
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return list.size()+1;//注意此處
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = layoutInflater.inflate(R.layout.camer_item, null);
mImageView = convertView.findViewById(R.id.iv_image);
delbtn=convertView.findViewById(R.id.bt_del);
if (position < list.size()) {
mImageView.setImageURI(list.get(position).getUri());
delbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
remove(position);
}
});
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LayoutInflater inflater = LayoutInflater.from(CamerDemo.this);
View imgEntryView = inflater.inflate(R.layout.largeicon, null); // 加載自定義的布局文件
final AlertDialog dialog = new AlertDialog.Builder(CamerDemo.this).create();
ImageView img = imgEntryView.findViewById(R.id.large_image);
Bitmap bitmap = ((BitmapDrawable) mImageView.getDrawable()).getBitmap();
img.setImageBitmap(bitmap);
dialog.setView(imgEntryView); // 自定義dialog
dialog.show();
// 點擊布局文件(也可以理解為點擊大圖)后關閉dialog,這里的dialog不需要按鈕
imgEntryView.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramView) {
dialog.cancel();
}
});
}
});
}else{
delbtn.setVisibility(View.GONE);
mImageView.setBackgroundResource(R.drawable.jiahao);//最后一個顯示加號圖片
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhrenli),""));
openCamera();
}
});
}
return convertView;
}
}
}
運行后效果:
由於用到BasdAdapter次數太多了,每次都要在當前頁面新建一個類來繼承BaseAdapter太麻煩了,每次都基本是拿以前的復制粘貼,然后修改不一樣的地方。所以我就想着如何將共有的部分分裝成一個通用類,需要改變的還在當前頁面實現,這樣就回省很多力氣了。
我們分析一下那些事公用的,首先適配這一塊適應所有。不同的地方也就是布局頁面,有的可能是一個imageview,有的可能是Button,或者EditText.這些都要根據不同頁面來定義,所以這個就要在當前頁面初始化。至於動態添加和刪除都是通用的。接下來我們就在自己封裝一下。
首先建一個通用的適配器AdapterHelper繼承BaseAdapter,這個類會被所有頁面用到。
package com.example.appview; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; import java.util.List; /* T1:傳入自定義得Model模型 T2:定義組件得類 */ public class AdapterHelper<T1 ,T2 extends AdapterInterface> extends BaseAdapter implements AdapterInterface { private Context context; public List<T1> list; //用於存放模型Model private T2 t; //初始化布局頁面組件的類 private int Rid; LayoutInflater layoutInflater; public AdapterHelper(){ } public AdapterHelper(Context context,List<T1> list,T2 t,int rid) { this.context = context; this.list = list; this.t=t; this.Rid=rid; layoutInflater = LayoutInflater.from(context); } //添加一個元素 public void add(T1 data) { if (list == null) { list = new ArrayList<>(); } list.add(data); notifyDataSetChanged(); } //往特定位置,添加一個元素 public void add(int position, T1 data) { if (list == null) { list= new ArrayList<>(); } list.add(position, data); notifyDataSetChanged(); } //移除當前數據的組件 public void remove(T1 data) { if (list != null) { list.remove(data); } notifyDataSetChanged(); } //移除當前位置的組件 public void remove(int position) { if (list != null) { list.remove(position); } notifyDataSetChanged(); } public void clear() { if (list != null) { list.clear(); } notifyDataSetChanged(); } @Override public int getCount() { return list.size()+1;//注意此處 } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { convertView= layoutInflater.inflate(Rid, null); return getView(convertView,position); } @Override public View getView(View view,int position) { return t.getView(view,position); } }
我們定義一個接口:
package com.example.appview;
import android.view.View;
public interface AdapterInterface{
public View getView(View view,int position);
}
我們就以上面的拍照頁面在頁面上定義布局頁面組件的初始化類:
private class CamerView implements AdapterInterface { @Override public View getView(View view, int position) { Button delbtn = view.findViewById(R.id.bt_del); ImageView imageView = view.findViewById(R.id.iv_image); if (position < adapter.getCount()-1) { imageView.setImageURI(adapter.list.get(position).getUri()); delbtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { adapter.remove(position); } }); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LayoutInflater inflater = LayoutInflater.from(CamerDemo.this); View imgEntryView = inflater.inflate(R.layout.largeicon, null); // 加載自定義的布局文件 final AlertDialog dialog = new AlertDialog.Builder(CamerDemo.this).create(); ImageView img = imgEntryView.findViewById(R.id.large_image); Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); // bigImageLoader(bitmap); img.setImageBitmap(bitmap); dialog.setView(imgEntryView); // 自定義dialog dialog.show(); // 點擊布局文件(也可以理解為點擊大圖)后關閉dialog,這里的dialog不需要按鈕 imgEntryView.setOnClickListener(new View.OnClickListener() { public void onClick(View paramView) { dialog.cancel(); } }); } }); }else{ delbtn.setVisibility(View.GONE); imageView.setBackgroundResource(R.drawable.jiahao);//最后一個顯示加號圖片 imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhrenli),"")); openCamera(); } }); } return view; } }
調用:
private List<CamerIcon> mDatas; private GridView mGridView; private AdapterHelper<CamerIcon,CamerView> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camer_demo); mGridView=findViewById(R.id.grid_photo); isOpenPhoto(); mDatas=new ArrayList<>(); //adapter=new GridViewAdapter(CamerDemo.this,mDatas); adapter= new AdapterHelper<>(CamerDemo.this, mDatas, new CamerView(), R.layout.camer_item); mGridView.setAdapter(adapter); }
整體代碼:
package com.example.appview; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.app.Dialog; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.Toast; import java.io.File; import java.util.ArrayList; import java.util.List; public class CamerDemo extends AppCompatActivity { private List<CamerIcon> mDatas; private GridView mGridView; // private GridViewAdapter adapter; private AdapterHelper<CamerIcon,CamerView> adapter; private File file= null; private Uri uri; private String filepath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camer_demo); mGridView=findViewById(R.id.grid_photo); isOpenPhoto(); initDatas(); //adapter=new GridViewAdapter(CamerDemo.this,mDatas); adapter= new AdapterHelper<>(CamerDemo.this, mDatas, new CamerView(), R.layout.camer_item); mGridView.setAdapter(adapter); } private void initDatas() { mDatas=new ArrayList<>(); //mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); // mDatas.add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhgongzuobaogao),"")); } /** * 得到資源文件中圖片的Uri * @param context 上下文對象 * @param id 資源id * @return Uri */ public Uri getUriFromDrawableRes(Context context, int id) { Resources resources = context.getResources(); String path = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + resources.getResourcePackageName(id) + "/" + resources.getResourceTypeName(id) + "/" + resources.getResourceEntryName(id); return Uri.parse(path); } public void openCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.addCategory(Intent.CATEGORY_DEFAULT); uri = getImageUri(); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, 1); } public Uri getImageUri() { file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".png"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } String path = file.getPath(); filepath=path; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { uri = Uri.fromFile(file); } else { //兼容android7.0 使用共享文件的形式 ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DATA, path); uri = this.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); } return uri; } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); // Bundle bundle = data.getExtras(); // Bitmap bitmap = (Bitmap) bundle.get("data");// 獲取相機返回的數據,並轉換為Bitmap圖片格式 // Uri uri; // if (data.getData() != null) // { // uri = data.getData(); // } // else // { // uri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, null,null)); // } if (requestCode==1){ // adapter.add(adapter.getCount()-2,new CamerIcon(uri,"dfsfs")); adapter.add(new CamerIcon(uri,"")); // Log.i("拍照","調用相機成功"); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(permissions[0].equals(android.Manifest.permission.CAMERA)){ if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ Toast.makeText(CamerDemo.this,"已授權",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "授權失敗", Toast.LENGTH_SHORT).show(); } } } /** * 判斷是否授權開啟攝像機功能 */ private void isOpenPhoto(){ if(Build.VERSION.SDK_INT>=23){ ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); int permission = ContextCompat.checkSelfPermission(CamerDemo.this.getApplicationContext(), android.Manifest.permission.CAMERA); if(permission== PackageManager.PERMISSION_GRANTED){ //如果有了相機的權限就調用相機 }else { AlertDialog.Builder builder=new AlertDialog.Builder(CamerDemo.this); builder.setTitle("提示"); builder.setMessage("是否開啟相機權限"); builder.setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //去請求相機權限 ActivityCompat.requestPermissions(CamerDemo.this,new String[]{android.Manifest.permission.CAMERA},0); } }); builder.setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(CamerDemo.this, "您拒絕了開啟相機權限", Toast.LENGTH_SHORT).show(); } }); builder.show(); } } } private class CamerView implements AdapterInterface { @Override public View getView(View view, int position) { Button delbtn = view.findViewById(R.id.bt_del); ImageView imageView = view.findViewById(R.id.iv_image); if (position < adapter.getCount()-1) { imageView.setImageURI(adapter.list.get(position).getUri()); delbtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { adapter.remove(position); } }); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LayoutInflater inflater = LayoutInflater.from(CamerDemo.this); View imgEntryView = inflater.inflate(R.layout.largeicon, null); // 加載自定義的布局文件 final AlertDialog dialog = new AlertDialog.Builder(CamerDemo.this).create(); ImageView img = imgEntryView.findViewById(R.id.large_image); Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); // bigImageLoader(bitmap); img.setImageBitmap(bitmap); dialog.setView(imgEntryView); // 自定義dialog dialog.show(); // 點擊布局文件(也可以理解為點擊大圖)后關閉dialog,這里的dialog不需要按鈕 imgEntryView.setOnClickListener(new View.OnClickListener() { public void onClick(View paramView) { dialog.cancel(); } }); } }); }else{ delbtn.setVisibility(View.GONE); imageView.setBackgroundResource(R.drawable.jiahao);//最后一個顯示加號圖片 imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // add(new CamerIcon(getUriFromDrawableRes(CamerDemo.this,R.drawable.zhrenli),"")); openCamera(); } }); } return view; } } }
這里已經封裝完了,這樣以后自定義的適配器就可以保持通用。
這里要注意一個細節,我定義了接口,為什么要定義這個接口。其實這個接口非常重要,沒有這個接口好多事情都很難做到。
我們來分析一下適配器類是如何繼承的,首先傳入兩個參數,第二個參數被約束了必須是繼承AdapterInterface接口,而適配器類本身也繼承了該接口。為什么要約束。因為T2傳入的這個就是初始化布局頁面中的組件類的。
也就是如果通過適配器來初始化布局頁面中的組件,那么適配器類必須要調用頁面中的CamerView類來初始化,但是如果這個類沒有的話,那么適配器類根本沒法調用CamerView中的初始化方法GetView來初始化。
如何把該方法放在接口AdapterInterface中,然后在AdapterHelper適配器方法T2參數約束他必須繼承Adapterinterface接口。那么我就可以確定這個方法在camerView類中一定存在。也就是說無論這個類存不存在,我都可以在AdapterHelper中調用GetView()方法。那么我怎末知道是adapterHelper調用的是哪個類呢?
在初始化AdapterHelper的時候直接傳入當前頁面的類T2的實例。和當前布局頁面的id值。就完美解決了。
這樣我們就通過泛型約束,和接口實現了適配器通用類的封裝。