日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

android仿华为系统相册之智能相册开发

發(fā)布時(shí)間:2024/1/8 windows 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android仿华为系统相册之智能相册开发 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、開(kāi)發(fā)內(nèi)容簡(jiǎn)介

最近課程要求仿照華為系統(tǒng)相冊(cè)做一個(gè)android相冊(cè)客戶(hù)端,我稱(chēng)之為智能相冊(cè)(智能是指其使用了機(jī)器學(xué)習(xí)的人臉識(shí)別、人臉檢測(cè)和分類(lèi)算法)。本著反正實(shí)驗(yàn)報(bào)告寫(xiě)了也是寫(xiě)了的心態(tài),還有自己在寫(xiě)的過(guò)程中搜索資料的時(shí)候發(fā)現(xiàn)其實(shí)好像有關(guān)于相冊(cè)列表獲取這部分內(nèi)容網(wǎng)上講的其實(shí)挺少的,雖然我的辦法并不是多么高明,在這里還是給大家分享一下,希望能對(duì)一些人起到幫助。

二、開(kāi)發(fā)內(nèi)容要求

智能相冊(cè)APP參照華為系統(tǒng)相冊(cè)的樣式和功能,主要分為三部分內(nèi)容:
  • 照片:顯示手機(jī)存儲(chǔ)的所有圖片
  • 相冊(cè):將手機(jī)的所有圖片按不同的相冊(cè)分類(lèi),點(diǎn)擊各個(gè)相冊(cè)查看其包含圖片
  • 分類(lèi):根據(jù)智能算法對(duì)手機(jī)存儲(chǔ)中的所有圖片進(jìn)行整理與分類(lèi),例如“人像”、“地點(diǎn)”、“事物”等

華為系統(tǒng)相冊(cè)樣式如下:

三、智能相冊(cè)效果展示

四、開(kāi)發(fā)過(guò)程詳述

(1)頂部導(dǎo)航欄的實(shí)現(xiàn)

頂部導(dǎo)航欄借用了github上的一個(gè)開(kāi)源第三方庫(kù)wasabeef/awesome-android-ui實(shí)現(xiàn),選取其中的SmartTabLayout控件,注意這里有andoridx和legacy android support library版本,我選取的是legacy android support library版本,具體實(shí)現(xiàn)如下:
  • build.gradle文件添加依賴(lài)
  • dependencies {compile 'com.ogaclejapan.smarttablayout:library:1.7.0@aar'//Optional: see how to use the utility.compile 'com.ogaclejapan.smarttablayout:utils-v4:1.7.0@aar'//Deprecated since 1.7.0compile 'com.ogaclejapan.smarttablayout:utils-v13:1.7.0@aar' }
  • activity_main.xml文件添加代碼如下:
  • <com.ogaclejapan.smarttablayout.SmartTabLayoutandroid:id="@+id/viewpagertab"android:layout_width="match_parent"android:layout_height="48dp"app:stl_indicatorAlwaysInCenter="false"app:stl_indicatorWithoutPadding="false"app:stl_indicatorInFront="true"app:stl_indicatorInterpolation="smart"app:stl_indicatorGravity="bottom"app:stl_indicatorColor="#40C4FF"app:stl_indicatorThickness="3dp"app:stl_indicatorWidth="auto"app:stl_indicatorCornerRadius="2dp"app:stl_overlineColor="@color/white"app:stl_overlineThickness="0dp"app:stl_underlineColor="@color/white"app:stl_underlineThickness="1dp"app:stl_dividerColor="@color/white"app:stl_dividerThickness="1dp"app:stl_defaultTabBackground="?attr/selectableItemBackground"app:stl_defaultTabTextAllCaps="true"app:stl_defaultTabTextColor="#FC000000"app:stl_defaultTabTextSize="16sp"app:stl_defaultTabTextHorizontalPadding="50dp"app:stl_defaultTabTextMinWidth="50dp"app:stl_distributeEvenly="true"app:stl_clickable="true"app:stl_titleOffset="24dp"app:stl_drawDecorationAfterTab="false"/><android.support.v4.view.ViewPagerandroid:id="@+id/viewpager"android:layout_marginTop="48dp"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/viewpagertab"/>
  • MainActivity.java文件設(shè)置Adapter和ViewPager,代碼如下:
  • FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter(getSupportFragmentManager(), FragmentPagerItems.with(this).add("照片", PageFragment1.class).add("相冊(cè)", PageFragment2.class).add("發(fā)現(xiàn)", PageFragment3.class).create());ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);viewPager.setAdapter(adapter);SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab);viewPagerTab.setViewPager(viewPager);

    到這里就順利完成了頂部導(dǎo)航欄的實(shí)現(xiàn)。


    (2)實(shí)現(xiàn)照片欄展示手機(jī)存儲(chǔ)中的所有圖片

    要展示手機(jī)中存儲(chǔ)的所有圖片,首先我們需要成功獲取到手機(jī)中所有圖片的路徑,通過(guò)圖片路徑訪問(wèn)圖片并把圖片加載出來(lái)。這個(gè)功能的實(shí)現(xiàn)主要分為以下幾個(gè)步驟:
  • 動(dòng)態(tài)申請(qǐng)讀取存儲(chǔ)權(quán)限
  • public static void verifyStoragePermissions(Activity activity) {try {//檢測(cè)是否有寫(xiě)的權(quán)限int permission = ActivityCompat.checkSelfPermission(activity,"android.permission.WRITE_EXTERNAL_STORAGE");if (permission != PackageManager.PERMISSION_GRANTED) {// 沒(méi)有寫(xiě)的權(quán)限,去申請(qǐng)寫(xiě)的權(quán)限,會(huì)彈出對(duì)話(huà)框ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);}}catch (Exception e) {e.printStackTrace();}}
  • 讀取手機(jī)存儲(chǔ)查找所有圖片并存儲(chǔ)圖片路徑以及其他相關(guān)信息。
    • 首先,我定義了一個(gè)數(shù)據(jù)類(lèi)SpacePhoto用于存儲(chǔ)每張圖片的相關(guān)信息(路徑,名稱(chēng)等),SpacePhoto數(shù)據(jù)類(lèi)實(shí)現(xiàn)了Parcelable類(lèi),Parcelable用來(lái)從一個(gè)組件傳輸高性能數(shù)據(jù)到另一個(gè)組件,在這里,我們將圖片的URL從相冊(cè)的縮略圖界面?zhèn)鬟f至SpacePhotoActivity。SpacePhoto數(shù)據(jù)類(lèi)定義如下:public class SpacePhoto implements Parcelable {private String mUrl;private String mTitle;public SpacePhoto(String url, String title) {mUrl = url;mTitle = title;}protected SpacePhoto(Parcel in) {mUrl = in.readString();mTitle = in.readString();}public static final Creator<SpacePhoto> CREATOR = new Creator<SpacePhoto>() {@Overridepublic SpacePhoto createFromParcel(Parcel in) {return new SpacePhoto(in);}@Overridepublic SpacePhoto[] newArray(int size) {return new SpacePhoto[size];}};public String getUrl() {return mUrl;}public void setUrl(String url) {mUrl = url;}public String getTitle() {return mTitle;}public void setTitle(String title) {mTitle = title;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel parcel, int i) {parcel.writeString(mUrl);parcel.writeString(mTitle);} }
    • 然后是使用ContentResolver組件查詢(xún)手機(jī)的所有圖片,代碼如下:Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;String[] projImage = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA,MediaStore.Images.Media.SIZE,MediaStore.Images.Media.DISPLAY_NAME};Cursor mCursor = getActivity().getContentResolver().query(mImageUri,projImage,MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?",new String[]{"image/jpeg", "image/png"},MediaStore.Images.Media.DATE_MODIFIED+" desc");if( mCursor != null ){while(mCursor.moveToNext()){String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));String displayName = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));all_photo_set.add(new SpacePhoto(path,displayName)); //將獲取到的路徑加入路徑集合 注意到一個(gè)問(wèn)題,由于相冊(cè)的初始頁(yè)面就是“照片”或者“分類(lèi)”,所以每次打開(kāi)APP的時(shí)候必須都能夠順利讀取手機(jī)存儲(chǔ)中的圖片,即每次打開(kāi)APP時(shí),都必須保證已獲取讀取手機(jī)存儲(chǔ)的權(quán)限。但是這樣就會(huì)面臨一個(gè)問(wèn)題,當(dāng)一部手機(jī)第一次安裝此APP時(shí),APP還沒(méi)有獲取到讀取手機(jī)存儲(chǔ)的權(quán)限(權(quán)限需要?jiǎng)討B(tài)獲取并由手機(jī)用戶(hù)決定是否允許讀取),則此時(shí)相冊(cè)的布局是無(wú)法加載出來(lái)的,會(huì)直接閃退。為解決此問(wèn)題,在APP中設(shè)置一個(gè)引導(dǎo)頁(yè),引導(dǎo)頁(yè)會(huì)在APP第一次被打開(kāi)時(shí)出現(xiàn)(以后便不會(huì)再出現(xiàn)),詢(xún)問(wèn)用戶(hù)是否給予讀取手機(jī)存儲(chǔ)的權(quán)限,進(jìn)而在進(jìn)入相冊(cè)的主頁(yè)面。另外,在引導(dǎo)頁(yè)還會(huì)完成對(duì)手機(jī)存儲(chǔ)掃描的全過(guò)程,獲取到手機(jī)中的所有圖片路徑,引導(dǎo)頁(yè)代碼如下:public class SplashActivity extends AppCompatActivity {private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE","android.permission.WRITE_EXTERNAL_STORAGE" }; private MyApplication app; private ArrayList<SpacePhoto> all_photo_set = new ArrayList<>(); // 存放所有圖片的路徑 private ArrayList<album> all_album = new ArrayList<>(); //按系統(tǒng)相冊(cè)所屬分開(kāi)照片 public static int MODE = Context.MODE_PRIVATE; private boolean isFirstIn; private SharedPreferences preferences; private Button enter_button;@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_splash);if (getSupportActionBar() != null){ // 去掉標(biāo)題欄getSupportActionBar().hide();}preferences = getSharedPreferences("first_pref", MODE_PRIVATE);isFirstIn = preferences.getBoolean("isFirstIn", true);if(isFirstIn){enter_button = findViewById(R.id.enter_button);enter_button.setVisibility(View.VISIBLE);verifyStoragePermissions(SplashActivity.this);SharedPreferences preferences = getSharedPreferences("first_pref", MODE_PRIVATE);SharedPreferences.Editor editor = preferences.edit();editor.putBoolean("isFirstIn", false);editor.commit();}else{enter_button = findViewById(R.id.enter_button);enter_button.setVisibility(View.VISIBLE);startActivity(new Intent(this,MainActivity.class));finish();} }public void search_all_picture() { // 獲取系統(tǒng)中所有圖片的路徑Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;String[] projImage = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA,MediaStore.Images.Media.SIZE,MediaStore.Images.Media.DISPLAY_NAME};Cursor mCursor = this.getContentResolver().query(mImageUri,projImage,MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?",new String[]{"image/jpeg", "image/png"},MediaStore.Images.Media.DATE_MODIFIED+" desc");if( mCursor != null ){while(mCursor.moveToNext()){String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));String displayName = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));all_photo_set.add(new SpacePhoto(path,displayName)); //將獲取到的路徑加入路徑集合String dirPath = new File(path).getParentFile().getAbsolutePath(); // 獲取該圖片的父路徑名int pdf = 0; //判斷此圖片所屬的相冊(cè)是否已存在,pdf為0表示圖片所屬的相冊(cè)還不存在for(int i = 0; i < all_album.size(); i++){if( all_album.get(i).getDirpath().equals(dirPath)){pdf = 1;all_album.get(i).add(new SpacePhoto(path,displayName));}}if( pdf == 0){ArrayList<SpacePhoto> new_list = new ArrayList<>();new_list.add(new SpacePhoto(path,displayName));String Str[] = dirPath.split("/");String album_name = Str[Str.length - 1];all_album.add(new album(new_list,dirPath,album_name));}}}} public static void verifyStoragePermissions(Activity activity) {try {//檢測(cè)是否有寫(xiě)的權(quán)限int permission = ActivityCompat.checkSelfPermission(activity,"android.permission.WRITE_EXTERNAL_STORAGE");if (permission != PackageManager.PERMISSION_GRANTED) {// 沒(méi)有寫(xiě)的權(quán)限,去申請(qǐng)寫(xiě)的權(quán)限,會(huì)彈出對(duì)話(huà)框ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);}}catch (Exception e) {e.printStackTrace();} }public void gotoMainAct(View view){search_all_picture();app = (MyApplication)getMyApplication();app.set_all_album(all_album);app.set_all_photo_set(all_photo_set);startActivity(new Intent(this,MainActivity.class));finish(); } } 這里我使用SharedPreferences來(lái)處理判斷用戶(hù)是否第一次打開(kāi)此APP的邏輯。
  • 成功獲取圖片的路徑集合后,根據(jù)路徑加載圖片將所有圖片展示出來(lái)
    • 實(shí)現(xiàn)圖片展示列表

      使用android提供的初始接口來(lái)根據(jù)圖片url加載圖片是比較麻煩的,首先要根據(jù)url獲取圖片的真實(shí)路徑,再根據(jù)真實(shí)路徑獲取bitmap數(shù)據(jù)類(lèi)型的圖片,最后再通過(guò)imageview控件展示出來(lái);其次還有圖片加載的性能問(wèn)題,因?yàn)閳D片展示列表要求快速加載系統(tǒng)中的所有圖片。針對(duì)以上問(wèn)題,我使用了一個(gè)第三方的Android開(kāi)源庫(kù)Glide。Glide是一個(gè)快速高效的Android圖片加載庫(kù),注重于平滑的滾動(dòng)。Glide提供了易用的API,高性能、可擴(kuò)展的圖片解碼管道(decode pipeline),以及自動(dòng)的資源池技術(shù)。Glide 支持拉取,解碼和展示視頻快照,圖片,和GIF動(dòng)畫(huà)。Glide的具體使用方法如下:
      • 在build.gradle文件中添加以下依賴(lài):
      // Glide compile 'com.github.bumptech.glide:glide:3.7.0'
      • 通過(guò)圖片url加載圖片
      Glide.with(mContext) //傳遞上下文.load(spacePhoto.getUrl()) // 目錄路徑或者URI或者URL.centerCrop() // 圖片有可能被裁剪.placeholder(R.drawable.error) //一個(gè)本地APP資源id,在圖片被加載前作為占位的圖片.into(imageView); // 要放置圖片的目標(biāo)imageView控件 使用Recyclerview來(lái)制作圖片展示列表,Recyclerview具體用法如下:
      • 在build.gradle文件中添加以下依賴(lài):
      // Recyclerview compile 'com.android.support:recyclerview-v7:25.1.1'
      • 自定義ImageGalleryAdapter,要求繼承RecyclerView.Adapter類(lèi),具體代碼如下:
      class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder> {private ArrayList<SpacePhoto> mSpacePhotos; private Context mContext;@Override public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {Context context = parent.getContext();LayoutInflater inflater = LayoutInflater.from(context);View photoView = inflater.inflate(R.layout.item_photo, parent, false);ImageGalleryAdapter.MyViewHolder viewHolder = new ImageGalleryAdapter.MyViewHolder(photoView);return viewHolder; }@Override public void onBindViewHolder(ImageGalleryAdapter.MyViewHolder holder, int position) {SpacePhoto spacePhoto = mSpacePhotos.get(position);ImageView imageView = holder.mPhotoImageView;Glide.with(mContext) //傳遞上下文.load(spacePhoto.getUrl()) // 目錄路徑或者URI或者URL.centerCrop() // 圖片有可能被裁剪.placeholder(R.drawable.error) //一個(gè)本地APP資源id,在圖片被加載前作為占位的圖片.into(imageView); // 要放置圖片的目標(biāo)imageView控件 }@Override public int getItemCount() {return (mSpacePhotos.size()); }public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {public ImageView mPhotoImageView;public MyViewHolder(View itemView) {super(itemView);mPhotoImageView = (ImageView) itemView.findViewById(R.id.iv_photo);itemView.setOnClickListener(this);}@Overridepublic void onClick(View view) {int position = getAdapterPosition();if(position != RecyclerView.NO_POSITION) {SpacePhoto spacePhoto = mSpacePhotos.get(position);String url = spacePhoto.getUrl();Intent intent = new Intent(mContext, SpacePhotoActivity.class);Bundle bundle = new Bundle();bundle.putString("url",url);intent.putExtras(bundle);mContext.startActivity(intent);}} }public ImageGalleryAdapter(Context context, ArrayList<SpacePhoto> spacePhotos) {mSpacePhotos = new ArrayList<>();mContext = context;mSpacePhotos = spacePhotos; } } 在fragement1顯示圖片展示列表,需要在PageFragment1.java文件的onCreateView函數(shù)返回一個(gè)View,該View加載的是fragment_page1 Laytout;并且,需要在onCreateView函數(shù)里設(shè)置Recyclerview的Adapter,具體代碼如下:@Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, // 系統(tǒng)會(huì)在Fragment首次繪制其用戶(hù)界面時(shí)調(diào)用此方法@Nullable Bundle savedInstanceState) {View root = inflater.inflate(R.layout.fragment_page1,container,false);search_all_picture();app = (MyApplication)getMyApplication();app.set_all_photo_set(all_photo_set); //放到Application中app.set_all_album(all_album);RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 2);RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.rv_images_1);recyclerView.setHasFixedSize(true);recyclerView.setLayoutManager(layoutManager);ImageGalleryAdapter adapter = new ImageGalleryAdapter(getActivity(), all_photo_set);//調(diào)用這個(gè)函數(shù)的時(shí)候SpacePhoto并不是空的recyclerView.setAdapter(adapter);return root; } fragment_page1.xml布局文件如下:<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v7.widget.RecyclerViewandroid:id="@+id/rv_images_1"android:layout_width="match_parent"android:layout_height="match_parent"/></android.support.design.widget.CoordinatorLayout>
    • 單擊圖片進(jìn)入圖片展示頁(yè)面

      我使用SpacePhotoActivity用于實(shí)現(xiàn)圖片展示頁(yè)面,在ImageGalleryAdapter類(lèi)中定義內(nèi)部類(lèi)MyViewHolder實(shí)現(xiàn)View.OnClickListener,并重載onclick函數(shù)如下:@Overridepublic void onClick(View view) {int position = getAdapterPosition();if(position != RecyclerView.NO_POSITION) {SpacePhoto spacePhoto = mSpacePhotos.get(position);String url = spacePhoto.getUrl();Intent intent = new Intent(mContext, SpacePhotoActivity.class);Bundle bundle = new Bundle();bundle.putString("url",url);intent.putExtras(bundle);mContext.startActivity(intent);}} 每次在圖片點(diǎn)擊列表單擊某個(gè)圖片,則跳轉(zhuǎn)到SpacePhotoActivity并展示被點(diǎn)擊的圖片,這里使用Intent中傳遞的是被點(diǎn)擊圖片的url,在SpacePhotoActivity中根據(jù)傳遞過(guò)來(lái)的圖片url加載圖片,代碼如下: mImageView = (ImageView) findViewById(R.id.image);Intent intent = getIntent();Bundle bundle = intent.getExtras();String url = bundle.getString("url");Glide.with(this).load(url).asBitmap().error(R.drawable.error).into(mImageView);

    到這里我們完成了讀取手機(jī)中的所有照片并將其展示出來(lái)的功能。


    (3)將手機(jī)的所有圖片按不同的相冊(cè)分類(lèi),點(diǎn)擊各個(gè)相冊(cè)查看其包含圖片

    • 獲取相冊(cè)列表沒(méi)有找到很好的方法,我們都知道獲取手機(jī)圖片要用到ContentResolver類(lèi),但是通過(guò)這個(gè)類(lèi)卻沒(méi)有辦法獲取到相冊(cè)。所以我采用了一種曲線救國(guó)的辦法:在獲取每張圖片的路徑的時(shí)候,同時(shí)獲取該圖片的父路徑,然后把父路徑相同的所有圖片歸結(jié)為一個(gè)相冊(cè)內(nèi)的圖片,雖然做法有點(diǎn)笨,但是效果還可以,獲取父路徑并按其分類(lèi)圖片的代碼如下:

      String dirPath = new File(path).getParentFile().getAbsolutePath(); // 獲取該圖片的父路徑名 int pdf = 0; //判斷此圖片所屬的相冊(cè)是否已存在,pdf為0表示圖片所屬的相冊(cè)還不存在 for(int i = 0; i < all_album.size(); i++){if( all_album.get(i).getDirpath().equals(dirPath)){pdf = 1;all_album.get(i).add(new SpacePhoto(path,displayName));} } if( pdf == 0){ArrayList<SpacePhoto> new_list = new ArrayList<>();new_list.add(new SpacePhoto(path,displayName));String Str[] = dirPath.split("/");String album_name = Str[Str.length - 1];all_album.add(new album(new_list,dirPath,album_name)); }

      為了更好地表示每個(gè)相冊(cè),我寫(xiě)了一個(gè)相冊(cè)數(shù)據(jù)類(lèi)album,包含三個(gè)屬性:

      • 一個(gè)用來(lái)存放該相冊(cè)所包含的圖片的Arraylist;
      • 相冊(cè)的名稱(chēng);
      • 該相冊(cè)內(nèi)所有圖片的父路徑;

      album數(shù)據(jù)類(lèi)的具體實(shí)現(xiàn)如下:

      public class album { private ArrayList<SpacePhoto> photo_set; private String album_name; private String dirpath;public album(ArrayList<SpacePhoto> list,String path,String str){photo_set = list;dirpath = path;album_name = str; } public void add(SpacePhoto item){photo_set.add(item); }public String getAlbum_name(){return album_name; }public String getDirpath(){return dirpath; }public int size(){return photo_set.size(); }public ArrayList<SpacePhoto> getPhotoList(){return photo_set; } }

      注意,album數(shù)據(jù)類(lèi)的album_name屬性的值是通過(guò)該相冊(cè)中所有圖片的公共父路徑來(lái)獲得的。仔細(xì)觀察路徑的表示方式,我發(fā)現(xiàn)獲取相冊(cè)名稱(chēng)可通過(guò)使用String.spilt函數(shù)分解父路徑字符串,獲取最后一個(gè)’/'之后的子串來(lái)表示。另外,我們還需要一個(gè)Arraylist來(lái)存儲(chǔ)所有的album。

    • 相冊(cè)界面要求展示出出相冊(cè)列表,所以將圖片按照相冊(cè)分類(lèi)好之后,還需要通過(guò)一個(gè)Listview來(lái)展示出相冊(cè)列表,ListView的實(shí)現(xiàn)比較簡(jiǎn)單,這里只貼一下代碼:

      public class listViewAdapter extends BaseAdapter {private ArrayList<album> list;private Context context;public listViewAdapter(ArrayList<album>list, Context context){this.list = list;this.context = context;}@Overridepublic int getCount() {if (list == null) {return 0;}return list.size();}@Overridepublic long getItemId(int i) {return i;}@Overridepublic Object getItem(int i) {if (list == null) {return null;}return list.get(i);}@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {// 通過(guò)inflate的方法加載布局,context需要在使用這個(gè)Adapter的Activity中傳入。if( view == null ){view = LayoutInflater.from(context).inflate(R.layout.album, null);}ImageView image = view.findViewById(R.id.cover);TextView album_name = view.findViewById(R.id.album_name);TextView picture_num = view.findViewById(R.id.picture_num);Glide.with(context) //傳遞上下文.load(list.get(i).getPhotoList().get(0).getUrl()) // 目錄路徑或者URI或者URL.centerCrop() // 圖片有可能被裁剪.placeholder(R.drawable.error) //一個(gè)本地APP資源id,在圖片被加載前作為占位的圖片.into(image); // 要放置圖片的目標(biāo)imageView控件picture_num.setText(list.get(i).size() + "張圖片");album_name.setText(list.get(i).getAlbum_name());return view; // 將這個(gè)處理好的view返回} }

      fragment_page2布局文件如下:

      <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ListViewandroid:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></android.support.design.widget.CoordinatorLayout>

      PageFragment2.java中為listview設(shè)置Adapter如下:

      albumAdapter = new listViewAdapter(app.get_all_album(),getActivity());listView = root.findViewById(R.id.listview);listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Intent intent = new Intent(getActivity(),album_show_page.class);Bundle bundle = new Bundle();bundle.putInt("index",position);intent.putExtras(bundle);startActivity(intent);}});listView.setAdapter(albumAdapter);

      點(diǎn)擊listview中的相冊(cè)可跳轉(zhuǎn)到album_show_page,顯示該相冊(cè)所包含的所有圖片,圖片列表實(shí)現(xiàn)的代碼只需復(fù)用fragment照片的即可。

    到這為止我們也順利實(shí)現(xiàn)了相冊(cè)欄。


    (4)關(guān)于照片fragment和相冊(cè)fragment實(shí)現(xiàn)內(nèi)容的補(bǔ)充——重寫(xiě)Application類(lèi)

    注意到照片欄和相冊(cè)欄的實(shí)現(xiàn)都需要首先獲取到手機(jī)存儲(chǔ)中的所有圖片,若在照片欄和相冊(cè)欄分別執(zhí)行一次查找手機(jī)存儲(chǔ)獲取圖片路徑的操作會(huì)顯得非常冗余;而且當(dāng)在相冊(cè)列表中每次點(diǎn)擊某個(gè)相冊(cè)時(shí),若采用Intent將整個(gè)相冊(cè)中圖片的url作為參數(shù)傳遞,則效率會(huì)非常低下。為了只進(jìn)行一次查找手機(jī)存儲(chǔ)的操作,很自然地想到可以將圖片路徑的集合設(shè)置為全局變量,這樣只要在整個(gè)項(xiàng)目的某一處進(jìn)行了查找手機(jī)存儲(chǔ)獲取了所有圖片路徑的操作,則之后就不再需要重復(fù)此操作。在android里聲明全局變量可通過(guò)重寫(xiě)Application類(lèi)來(lái)實(shí)現(xiàn)。Application和Activity,Service一樣是android框架的一個(gè)系統(tǒng)組件,當(dāng)android程序啟動(dòng)時(shí)系統(tǒng)會(huì)創(chuàng)建一個(gè)application對(duì)象,用來(lái)存儲(chǔ)系統(tǒng)的一些信息。通常我們是不需要指定一個(gè)Application的,這時(shí)系統(tǒng)會(huì)自動(dòng)幫我們創(chuàng)建。打開(kāi)每一個(gè)應(yīng)用程序的manifest文件,可以看到activity都是包含在application標(biāo)簽之中的。android系統(tǒng)會(huì)為每個(gè)程序運(yùn)行時(shí)創(chuàng)建一個(gè)Application類(lèi)的對(duì)象且僅創(chuàng)建一個(gè),所以Application是單例 (singleton)模式的一個(gè)類(lèi).且application對(duì)象的生命周期是整個(gè)程序中最長(zhǎng)的,它的生命周期就等于這個(gè)程序的生命周期。因?yàn)樗侨值膯卫?#xff0c;所以在不同的Activity,Service中獲得的對(duì)象都是同一個(gè)對(duì)象。因此在android中我們可以避免使用靜態(tài)變量來(lái)存儲(chǔ)長(zhǎng)久保存的值,而用Application。為了更好的利用Application的這一特性,比如我們需要Application來(lái)保存一些靜態(tài)值,需要自定義繼承于Application的類(lèi),然后在這個(gè)類(lèi)中定義一個(gè)變量來(lái)保存。在默認(rèn)情況下應(yīng)用系統(tǒng)會(huì)自動(dòng)生成Application 對(duì)象,但是如果我們自定義了Application,那就需要告知系統(tǒng),實(shí)例化的時(shí)候,是實(shí)例化我們自定義的,而非默認(rèn)的。為了讓系統(tǒng)實(shí)例化的時(shí)候找到,我們必須在manifest中修改application標(biāo)簽屬性,代碼如下: <applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme">android:name=".MyApplication"<activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".SpacePhotoActivity" /><activity android:name=".album_show_page"></activity></application>

    其中,最關(guān)鍵的是這一句:android:name=".MyApplication"。

    重寫(xiě)的MyApplication類(lèi)如下:

    public class MyApplication extends Application{private static MyApplication instance;private static ArrayList<SpacePhoto> all_photo_set = new ArrayList<>(); // 存放所有圖片的路徑private static ArrayList<album> all_album = new ArrayList<>(); //按系統(tǒng)相冊(cè)所屬分開(kāi)照片// 獲取Applicationpublic static Context getMyApplication() {return instance;}public static ArrayList<SpacePhoto> get_all_photo_set(){return all_photo_set;}public static ArrayList<album> get_all_album(){return all_album;}public static void set_all_photo_set(ArrayList<SpacePhoto> copy){all_photo_set = copy;}public static void set_all_album(ArrayList<album> copy){all_album = copy;} }

    由以上代碼可知,MyApplication類(lèi)中既存放了所有的路徑集合,也存放了按照相冊(cè)分好的路徑集合,在任何需要這些數(shù)據(jù)的地方,只要根據(jù)相應(yīng)的函數(shù)進(jìn)行請(qǐng)求即可。在需要獲取全局對(duì)象的地方,通過(guò)以下代碼獲取application單例:

    app = (MyApplication)getMyApplication();

    在相冊(cè)列表界面,點(diǎn)擊相冊(cè)跳轉(zhuǎn)到該相冊(cè)的圖片展示列表,其中intent傳遞的不是該相冊(cè)所有圖片的url,而是該album在ArrayList中的下標(biāo),在show_album_page Activity中,只要根據(jù)下標(biāo)進(jìn)行請(qǐng)求數(shù)據(jù)即可。


    關(guān)于分類(lèi)欄的分類(lèi)算法,由于涉及科研隱私,在這里就不說(shuō)了,文章很長(zhǎng),謝謝閱讀。

    總結(jié)

    以上是生活随笔為你收集整理的android仿华为系统相册之智能相册开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产一区二区在线播放视频 | 琪琪午夜伦理影院7777 | 欧美人与动牲交a欧美精品 欧美三级在线看 | 国产av电影一区二区三区 | 国产女人18水真多18精品一级做 | 黄网在线免费观看 | jizzjizz在线播放 | 人妖一区二区三区 | 91久久一区 | 欧美有码在线 | 蜜桃tv在线观看 | 天天摸天天插 | 日日骚一区 | 欧美另类一区 | 国产第一精品视频 | 天堂中文视频在线 | 18禁免费无码无遮挡不卡网站 | 精品午夜一区二区三区 | 在线免费看黄网站 | 精品视频一区二区三区四区 | 日韩视频免费观看高清 | 大陆av片| 操韩国美女| 日韩精品视频在线免费观看 | 欧美日韩一区二区在线 | 热re99久久精品国产99热 | 亚洲精品综合在线 | 欧美偷拍一区二区三区 | 国产亚洲精品久久久久久久 | 国产欧美精品国产国产专区 | 在线观看入口 | 国产粉嫩呻吟一区二区三区 | 一起操网址 | 神宫寺奈绪一区二区三区 | 黄色一大片 | 婷婷中文 | 久久看视频 | 亚洲自拍偷拍一区二区三区 | 日韩视频在线免费播放 | 成人在线免费av | 天天色天天射天天干 | 亚洲h在线观看 | 91导航 | 欧美一级大片在线观看 | 高跟鞋和丝袜猛烈xxxxxx | 国产亚洲精品成人无码精品网站 | 色屁屁一区二区三区视频 | 人妻少妇一区二区三区 | 学生调教贱奴丨vk | 国产区精品在线 | 高h捆绑拘束调教小说 | 天海翼一区 | 2019中文在线观看 | 一区二区男女 | 亚洲日本三级 | 亚洲视频精品在线观看 | 在线观看国产免费av | 国产精品美女www爽爽爽 | 久久福利影院 | 国产熟妇乱xxxxx大屁股网 | 国产免费二区 | 91视频大全 | 麻豆高清| 天天做天天爱天天爽综合网 | 国产精品一区二区在线观看 | 日韩福利视频一区 | 男男play呻吟动漫网站 | 亚洲一区二区三区加勒比 | 奇米777色| 中文字幕在线高清 | av中文在线资源 | 91婷婷色 | 亚洲少妇第一页 | 美女隐私无遮挡免费 | 亚洲无圣光 | 欧美亚色 | 狠狠做深爱婷婷综合一区 | 无码人妻精品一区二区三区温州 | 97精品超碰一区二区三区 | 午夜看看 | 亚洲专区区免费 | 久久大综合 | 日本不卡视频在线观看 | 国产男女自拍 | 中文字幕在线观看一区二区三区 | 亚洲乱熟女一区二区 | 77777av | 国产精品66| 久久色婷婷| 日韩美女毛片 | 国产精品三级久久久久久电影 | 亚洲成人免费影院 | 日本r级电影在线观看 | 美女又黄又免费 | 日本欧美在线播放 | 亚洲成人网在线播放 | 欧美日韩亚洲精品内裤 | 久久在线电影 | 亚洲1页|