精华内容
下载资源
问答
  • 有时候需要对一些数据进行分类显示,还要显示他们的分类标题,普通的GridView是挺难实现的,因为GridView不支持不同行自定义列数,例如我想标题占满一行,其他子项每两个占一行。GridView也可以实现,需要对GridView...
  • 仿ios时间轴相册(带预览选择以及浮动头部功能) 时间轴相册 带浮动日期头部 照片按时间分类 按照相册文件夹分类设置最大选择数量 可预览并可选择图片跳转 不同相册选择的图片都会放在一起
  • 人脸识别图片分类检索系统...照片按人脸进行分类,实现了人脸入库,分类检索,1:1比对和1:N比对,免费版可设置500张照片。 每秒比对人脸5-6万张。实现了百万级数据库分秒检索完成。正脸情况下可以达到97%以上的成功率。
  • 本例的目的是实现类似于QQ的照片选择功能。选择照片之后,使用类似于新浪微博 发微博 页面进行展示。 先上效果图: ...2.对1中获取的图片,以图片所属的父...3.选择照片页面 与 选择相册页面 相互切换并且不走onCrea

    本例的目的是实现类似于QQ的照片选择功能。选择照片之后,使用类似于新浪微博 发微博 页面进行展示。

    先上效果图:

          


    本例中使用的主要技术:

    1.使用ContentProvider读取SD卡所有图片信息。

    2.对1中获取的图片,以图片所属的父文件夹进行分类(类似于QQ)。

    3.选择照片页面 与 选择相册页面 相互切换并且不走onCreate(切换十分流畅),同时设置页面切换动画以提升用户体验。

    4.加载SD卡图片时使用LruCache,并设置初始压缩比例,减少内存占用。

    5.“正方形布局”SquareRelativeLayout的使用(一个继承自RelativeLayout的自定义组件,会自适应保持自己为正方形)。


    代码较多,此处就不贴了。有兴趣的请下载源码查看(免积分哦!):

    download.csdn.net/detail/books1958/8145321


    展开全文
  • 手机相册,你使用时候想要实现什么?想备份给手机瘦身?想要分类相册?想要简洁好操作?...虽然非会员传视频会损失画质,但如果只是传照片的需求可以用它,不过需要记得把权限设置为仅自己可见。相册管...

    手机相册,你使用时候想要实现什么?想备份给手机瘦身?想要分类相册?想要简洁好操作?还是无限空间?还是方便清理相册?恐怕十全十美的云相册,但是依我看满足以上要求越多的,就越是好APP,最近发现一款APP一刻相册和其他几款,我来总结一下。

    QQ空间——没有空间限制的好代表,用来传照片原图还是非常给力的。虽然非会员传视频会损失画质,但如果只是传照片的需求可以用它,不过需要记得把权限设置为仅自己可见。

    相册管家——个人体验非常不好用。首先是账号不能互通,其次是存储空间少,广告又比较多,而且自动生成的故事不太准确,所以我觉得它比较鸡肋,不及手机自带相册。

    时光相册——体验上挺好的。虽然颜值上稍差一点,但自动备份非常快,可以直接删除已经备份过的照片来清理手机内存。不过视图上没有年月日的视图,只有日视图,翻照片比较困难

    30402ba8384ed5e86d82b53cbfc7d5a5.png

    百度网盘的相册——传视频要会员,这点非常不友好,而且它夹杂在百度网盘之中,藏得比较深,不能一打开app就查看,同时只能查看备份上去的照片,不能查看本地未备份的照片,这是硬伤。

    一刻相册——背靠百度网盘品牌,安全性是可以保障的。同时可以导入网盘的照片,能解决百度网盘非要会员才能传视频的问题。整体版面风格简洁,看起来会比较清爽,颜值比时光相册能打一些。视图是和手机相册一致的年月日形式,查看起来很方便。空间上能通过邀请好友获得无限空间。在分享功能上,除了微信、微博等分享,还能碰一碰免流量传输照片。还有时下最热的卡点视频一键制作功能,不用教程,小白零基础上手,横屏竖屏任意选,就是模板少点,但是整体还是很方便实用的。备份的速度很快,备份后是原画质,且系统会按照地点、时间、人物等类型分类整理照片,不过有时候备份完的顺序好像和本地相册里的不太一致,有时候找不到。还有就是和时光相册一样,支持备份完成一键清理本地照片,给手机省内存,如果以后有需要还能再从APP里下载原图。

    2187de7b16a6d50ffe737553c547e9da.png

    其实就单纯的相册APP来说,时光相册和一刻相册都是很好用的,综合实力考虑的情况下,我选择一刻相册,毕竟这是最新出的云相册,又这么好用,哈哈。

    展开全文
  • 应用在Mac平台上的ImageRanger软件是一款非常强大的照片管理...如何在ImageRanger中设置人脸识别? 如何设置人脸识别 通过面部识别,您可以与朋友和家人一起选择并轻松搜索照片。1、首先按“ 选择面部”按钮。 ...

    应用在Mac平台上的ImageRanger软件是一款非常强大的照片管理软件,ImageRanger Pro Mac帮助您在处理大型集合时过滤和搜索图像。当您打开包含图像文件的任何文件夹时,ImageRanger会构建内部索引以加快图像搜索速度。如何在ImageRanger中设置人脸识别?

    如何设置人脸识别

    通过面部识别,您可以与朋友和家人一起选择并轻松搜索照片。1、首先按“ 选择面部”按钮。
    2、单击图像上的面。按加号按钮可将新人添加到已知人员列表中。
    3、添加新人后,您可以使用主窗口顶部的“ 人物”过滤器选择此人的照片。

    展开全文
  • android仿华为系统相册之智能相册开发

    千次阅读 多人点赞 2019-05-07 23:24:18
    最近课程要求仿照华为系统相册做一个android相册客户端,我称之为智能相册(智能是指其使用了机器学习的人脸识别、人脸检测和分类算法)。本着反正实验报告写了也是写了的心态,还有自己在写的过程中搜索资料的时候...

    一、开发内容简介

    最近课程要求仿照华为系统相册做一个android相册客户端,我称之为智能相册(智能是指其使用了机器学习的人脸识别、人脸检测和分类算法)。本着反正实验报告写了也是写了的心态,还有自己在写的过程中搜索资料的时候发现其实好像有关于相册列表获取这部分内容网上讲的其实挺少的,虽然我的办法并不是多么高明,在这里还是给大家分享一下,希望能对一些人起到帮助。

    二、开发内容要求

    智能相册APP参照华为系统相册的样式和功能,主要分为三部分内容:
    • 照片:显示手机存储的所有图片
    • 相册:将手机的所有图片按不同的相册分类,点击各个相册查看其包含图片
    • 分类:根据智能算法对手机存储中的所有图片进行整理与分类,例如“人像”、“地点”、“事物”等

    华为系统相册样式如下:

    三、智能相册效果展示

    四、开发过程详述

    (1)顶部导航栏的实现

    顶部导航栏借用了github上的一个开源第三方库wasabeef/awesome-android-ui实现,选取其中的SmartTabLayout控件,注意这里有andoridx和legacy android support library版本,我选取的是legacy android support library版本,具体实现如下:
    1. build.gradle文件添加依赖
    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.0
        compile 'com.ogaclejapan.smarttablayout:utils-v13:1.7.0@aar'
    } 
    
    1. activity_main.xml文件添加代码如下:
    <com.ogaclejapan.smarttablayout.SmartTabLayout
            android: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.ViewPager
            android:id="@+id/viewpager"
            android:layout_marginTop="48dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/viewpagertab"
            />
    
    
    1. MainActivity.java文件设置Adapter和ViewPager,代码如下:
    FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter(
                    getSupportFragmentManager(), FragmentPagerItems.with(this)
                    .add("照片", PageFragment1.class)
                    .add("相册", PageFragment2.class)
                    .add("发现", PageFragment3.class)
                    .create());
    
            ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
            viewPager.setAdapter(adapter);
    
            SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab);
            viewPagerTab.setViewPager(viewPager);
    

    到这里就顺利完成了顶部导航栏的实现。


    (2)实现照片栏展示手机存储中的所有图片

    要展示手机中存储的所有图片,首先我们需要成功获取到手机中所有图片的路径,通过图片路径访问图片并把图片加载出来。这个功能的实现主要分为以下几个步骤:
    1. 动态申请读取存储权限
    public static void verifyStoragePermissions(Activity activity) {
            try {
    
                //检测是否有写的权限
                int permission = ActivityCompat.checkSelfPermission(activity,
                        "android.permission.WRITE_EXTERNAL_STORAGE");
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    // 没有写的权限,去申请写的权限,会弹出对话框
                    ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    1. 读取手机存储查找所有图片并存储图片路径以及其他相关信息。
    • 首先,我定义了一个数据类SpacePhoto用于存储每张图片的相关信息(路径,名称等),SpacePhoto数据类实现了Parcelable类,Parcelable用来从一个组件传输高性能数据到另一个组件,在这里,我们将图片的URL从相册的缩略图界面传递至SpacePhotoActivity。SpacePhoto数据类定义如下:
      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>() {
              @Override
              public SpacePhoto createFromParcel(Parcel in) {
                  return new SpacePhoto(in);
              }
      
              @Override
              public 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;
          }
      
      
          @Override
          public int describeContents() {
              return 0;
          }
      
          @Override
          public void writeToParcel(Parcel parcel, int i) {
              parcel.writeString(mUrl);
              parcel.writeString(mTitle);
          }
      }
      
    • 然后是使用ContentResolver组件查询手机的所有图片,代码如下:
      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)); //将获取到的路径加入路径集合
      
      注意到一个问题,由于相册的初始页面就是“照片”或者“分类”,所以每次打开APP的时候必须都能够顺利读取手机存储中的图片,即每次打开APP时,都必须保证已获取读取手机存储的权限。但是这样就会面临一个问题,当一部手机第一次安装此APP时,APP还没有获取到读取手机存储的权限(权限需要动态获取并由手机用户决定是否允许读取),则此时相册的布局是无法加载出来的,会直接闪退。为解决此问题,在APP中设置一个引导页,引导页会在APP第一次被打开时出现(以后便不会再出现),询问用户是否给予读取手机存储的权限,进而在进入相册的主页面。另外,在引导页还会完成对手机存储扫描的全过程,获取到手机中的所有图片路径,引导页代码如下:
      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<>(); //按系统相册所属分开照片
      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){  // 去掉标题栏
              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() { // 获取系统中所有图片的路径
          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; //判断此图片所属的相册是否已存在,pdf为0表示图片所属的相册还不存在
                  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 {
      
              //检测是否有写的权限
              int permission = ActivityCompat.checkSelfPermission(activity,
                      "android.permission.WRITE_EXTERNAL_STORAGE");
              if (permission != PackageManager.PERMISSION_GRANTED) {
                  // 没有写的权限,去申请写的权限,会弹出对话框
                  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来处理判断用户是否第一次打开此APP的逻辑。
    1. 成功获取图片的路径集合后,根据路径加载图片将所有图片展示出来
    • 实现图片展示列表

      使用android提供的初始接口来根据图片url加载图片是比较麻烦的,首先要根据url获取图片的真实路径,再根据真实路径获取bitmap数据类型的图片,最后再通过imageview控件展示出来;其次还有图片加载的性能问题,因为图片展示列表要求快速加载系统中的所有图片。针对以上问题,我使用了一个第三方的Android开源库Glide。Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的具体使用方法如下:
      • 在build.gradle文件中添加以下依赖:
      // Glide
      compile 'com.github.bumptech.glide:glide:3.7.0'
      
      • 通过图片url加载图片
      Glide.with(mContext) //传递上下文
                  .load(spacePhoto.getUrl()) // 目录路径或者URI或者URL
                  .centerCrop() // 图片有可能被裁剪
                  .placeholder(R.drawable.error) //一个本地APP资源id,在图片被加载前作为占位的图片
                  .into(imageView); // 要放置图片的目标imageView控件
      
      使用Recyclerview来制作图片展示列表,Recyclerview具体用法如下:
      • 在build.gradle文件中添加以下依赖:
      // Recyclerview
      compile 'com.android.support:recyclerview-v7:25.1.1'
      
      • 自定义ImageGalleryAdapter,要求继承RecyclerView.Adapter类,具体代码如下:
      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) //一个本地APP资源id,在图片被加载前作为占位的图片
                  .into(imageView); // 要放置图片的目标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);
          }
      
          @Override
          public 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函数返回一个View,该View加载的是fragment_page1 Laytout;并且,需要在onCreateView函数里设置Recyclerview的Adapter,具体代码如下:
      @Override
      public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, // 系统会在Fragment首次绘制其用户界面时调用此方法
                               @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);
          //调用这个函数的时候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.RecyclerView
          android:id="@+id/rv_images_1"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
      
      </android.support.design.widget.CoordinatorLayout>
      
    • 单击图片进入图片展示页面

      我使用SpacePhotoActivity用于实现图片展示页面,在ImageGalleryAdapter类中定义内部类MyViewHolder实现View.OnClickListener,并重载onclick函数如下:
      @Override
          public 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);
              }
          }
      
      每次在图片点击列表单击某个图片,则跳转到SpacePhotoActivity并展示被点击的图片,这里使用Intent中传递的是被点击图片的url,在SpacePhotoActivity中根据传递过来的图片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);
                  
      

    到这里我们完成了读取手机中的所有照片并将其展示出来的功能。


    (3)将手机的所有图片按不同的相册分类,点击各个相册查看其包含图片

    • 获取相册列表没有找到很好的方法,我们都知道获取手机图片要用到ContentResolver类,但是通过这个类却没有办法获取到相册。所以我采用了一种曲线救国的办法:在获取每张图片的路径的时候,同时获取该图片的父路径,然后把父路径相同的所有图片归结为一个相册内的图片,虽然做法有点笨,但是效果还可以,获取父路径并按其分类图片的代码如下:

      String dirPath = new File(path).getParentFile().getAbsolutePath(); // 获取该图片的父路径名
      int pdf = 0; //判断此图片所属的相册是否已存在,pdf为0表示图片所属的相册还不存在
      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));
      }
      

      为了更好地表示每个相册,我写了一个相册数据类album,包含三个属性:

      • 一个用来存放该相册所包含的图片的Arraylist;
      • 相册的名称;
      • 该相册内所有图片的父路径;

      album数据类的具体实现如下:

      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数据类的album_name属性的值是通过该相册中所有图片的公共父路径来获得的。仔细观察路径的表示方式,我发现获取相册名称可通过使用String.spilt函数分解父路径字符串,获取最后一个’/'之后的子串来表示。另外,我们还需要一个Arraylist来存储所有的album。

    • 相册界面要求展示出出相册列表,所以将图片按照相册分类好之后,还需要通过一个Listview来展示出相册列表,ListView的实现比较简单,这里只贴一下代码:

      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;
          }
      
      
          @Override
          public int getCount() {
              if (list == null) {
                  return 0;
              }
              return list.size();
          }
      
          @Override
          public long getItemId(int i) {
              return i;
          }
      
          @Override
          public Object getItem(int i) {
              if (list == null) {
                  return null;
              }
              return list.get(i);
          }
          @Override
          public View getView(int i, View view, ViewGroup viewGroup) {
              // 通过inflate的方法加载布局,context需要在使用这个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) //一个本地APP资源id,在图片被加载前作为占位的图片
                      .into(image); // 要放置图片的目标imageView控件
              
              picture_num.setText(list.get(i).size() + "张图片");
              album_name.setText(list.get(i).getAlbum_name());
      
              return view; // 将这个处理好的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">
      
      <ListView
          android:id="@+id/listview"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
      
      </ListView>
      
      </android.support.design.widget.CoordinatorLayout>
      

      PageFragment2.java中为listview设置Adapter如下:

      albumAdapter = new listViewAdapter(app.get_all_album(),getActivity());
          listView = root.findViewById(R.id.listview);
          listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
              @Override
              public 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);
      

      点击listview中的相册可跳转到album_show_page,显示该相册所包含的所有图片,图片列表实现的代码只需复用fragment照片的即可。

    到这为止我们也顺利实现了相册栏。


    (4)关于照片fragment和相册fragment实现内容的补充——重写Application类

    注意到照片栏和相册栏的实现都需要首先获取到手机存储中的所有图片,若在照片栏和相册栏分别执行一次查找手机存储获取图片路径的操作会显得非常冗余;而且当在相册列表中每次点击某个相册时,若采用Intent将整个相册中图片的url作为参数传递,则效率会非常低下。为了只进行一次查找手机存储的操作,很自然地想到可以将图片路径的集合设置为全局变量,这样只要在整个项目的某一处进行了查找手机存储获取了所有图片路径的操作,则之后就不再需要重复此操作。在android里声明全局变量可通过重写Application类来实现。Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建。打开每一个应用程序的manifest文件,可以看到activity都是包含在application标签之中的。android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。因此在android中我们可以避免使用静态变量来存储长久保存的值,而用Application。为了更好的利用Application的这一特性,比如我们需要Application来保存一些静态值,需要自定义继承于Application的类,然后在这个类中定义一个变量来保存。在默认情况下应用系统会自动生成Application 对象,但是如果我们自定义了Application,那就需要告知系统,实例化的时候,是实例化我们自定义的,而非默认的。为了让系统实例化的时候找到,我们必须在manifest中修改application标签属性,代码如下:
    <application
            android: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>
            <activity
                android:name=".SpacePhotoActivity" />
            <activity android:name=".album_show_page"></activity>
        </application>
    

    其中,最关键的是这一句:android:name=".MyApplication"。

    重写的MyApplication类如下:

    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<>(); //按系统相册所属分开照片
    
        // 获取Application
        public 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类中既存放了所有的路径集合,也存放了按照相册分好的路径集合,在任何需要这些数据的地方,只要根据相应的函数进行请求即可。在需要获取全局对象的地方,通过以下代码获取application单例:

    app = (MyApplication)getMyApplication();
    

    在相册列表界面,点击相册跳转到该相册的图片展示列表,其中intent传递的不是该相册所有图片的url,而是该album在ArrayList中的下标,在show_album_page Activity中,只要根据下标进行请求数据即可。


    关于分类栏的分类算法,由于涉及科研隐私,在这里就不说了,文章很长,谢谢阅读。
    展开全文
  • 获取手机相册,点击每个相册之后进入该相册的图片列表界面,在图片列表界面可以实现图片多选,然后进入所选择的图片界面,在该界面内可以实现所选图片的上传等功能。 该项目最大特色: 1、获取相册列表,目前网络...
  • wordpress相册Have you ever wanted to organize your photo galleries with albums? While image galleries allow you to display multiple photos on a single page, albums can allow you to display multiple ...
  • 奈何图片实在太多,不可能去单个去一个个保存,太费时间,今天来给大家分享怎样将又拍相册分类页的多个相册快速保存到电脑上,下面来看操作。 首先打开又拍网的相册页面上,在“全部分类”的页面上,复制上方的链接...
  • 52COVER相册系统 v1.2.rar

    2019-07-06 03:45:24
    多说评论系统关联(独立评论管理)标题(Title)关键词(KeyWords)描述(Description)同时数据库自动调用关联相册分类及照片信息,助于seo 52COVER相册系统前台页面 52COVER相册系统后台管理 后台路径:域名/...
  • iOS开发学习路线

    千次阅读 2018-04-23 09:37:26
    初级iOS开发iOS中级开发说白了,就是你学会了基本的UI界面搭建,上架,沉淀一段时间,你觉得自己还适合这门行业,还适合,还能接受 这个所谓的iOS开发工程师的行业.你就可以说是一名中级iOS开发. 这个沉淀时间 大约在1年...
  • 史上最全面Java面试汇总(面试题+答案)

    万次阅读 多人点赞 2018-07-06 14:09:25
    封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行封装隐藏。封装分为属性的封装和方法的封装。 继承:是对有着共同特性的多类事物,进行再抽象成一个类。这...
  • 设置上传文件,文件夹路径命名规则,文件夹分类功能 连接上传,图片软删除 OTA平滑升级系统 (暗)暗黑主题 IP封禁功能(支持通配符) 自定义链接参数 单用户模式 图片广场... :hammer_and_wrench:安装要求 P
  • 支持无限极分类和自定义菜单的相册源码,有4钟相册权限支持,还有标签及回收站功能! MeiuPic 2.2.0正式发布! 2.2.0 新加入的功能: 1. 加入全新的风格"Sense" 2. 加入登录验证码和评论验证码 3. 模板功能增强...
  • 52COVER相册系统 1.2.rar

    2019-05-23 15:29:04
    52COVER相册系统是一款...信息安全过滤(保证数据库安全屏蔽非法代码的入侵)多说评论系统关联(独立评论管理)标题(Title)关键词(KeyWords)描述(Description)同时数据库自动调用关联相册分类及照片信息,助于seo
  • 调用系统相机和相册(iPad,iPhone) 打开相机:(iPad,iPhone) //先设定sourceType为相机,然后判断相机是否可用(ipod)没相机,不可用将sourceType设定为相片库 ...
  • MeiuPic美优相册管理系统官方版v2.2.0 功能介绍: 系统内置主题拥有五种色调的预置风格,满足您各式各样的个人风格及心情,当然您也可以搭配出更加个性的风格。 如果这些还不能满足你的要求,更有简洁、时尚、酷炫...
  • 桃源相册管理系统v2.3

    2014-07-15 17:27:29
    40.可设置相册及照片的推荐,模板调用。 41.管理员在后台可统一设置用户上传照片后添加的水印。 42.可设置照片需审核后才能显示已共享的照片。 43.导入用户功能,支持ACCESS或Excel中导出的TXT格式信息,分项目一次...
  • 方法/步骤在手机上打开清爽视频编辑器,有视频编辑、美拍美摄、电子相册、特效模板、动感视频、创意视频、动态字幕、视频变音、精美滤镜、配音配乐等等功能。其中的“动感视频”这一功能就是我们需要的,直接点击...
  • 移动WEB--仿手机原生相册(Vue版)

    千次阅读 2017-11-30 23:05:01
    //调用move方法, 设置gallery元素的transform, 移动图片 this .move(dx); }, moveEnd: function (event) { if ( this .isTouchStart) { //移动图片的时候, 需要动画, 动画采用css3的transition实现 ...
  • 一键设置分类相册封面,自定义相册排序方式,正序或倒序; 相册集成HighSlide、LightBox、GreyBox、ThickBox特效,并可以使用外部的Z-Blog插件; 停用时自动删除生成的文件,替换添加的导航,一键安装
  • 可以按照片分类(风景,人物,等),同时也可以按相册分类. 本相册采用优化算法与数据存贮结构,占用空间极小,数据库增长非常缓慢.(实际测试,在照片增加到1000张的时候,数据库不足800K),是个人主页展 示个人风采,...
  •  回归正题,自定义的东西也比较多,上个周翻UI图,忽然看见一个时间轴的相册的东西,当时一看直接用了知乎的一个图片选择器框架,本来想去改进一番,想来想去还是自己写一个吧(其实是看不懂,不太好下手) ...
  • * 相册可以设置公开或个人,个人相册登录后才可以看到 * 可以通过加密的网址把个人相册或照片分享给朋友或家人 * 按需生成各种尺寸的缩略图 * 缩略图根据访问自动生成,而不是上传时生成 * 原始图片被保留但对...
  • Android 相册图库功能,按时间排序

    千次阅读 2018-08-19 23:10:14
    TimeAlbum 时间相册 功能说明 1、图片和视频资源根据日期排序显示。 2、图片视频预览功能,图片、视频预览带缓存功能。 3、单个图片或视频可进行删除及分享操作。 4、多张图片进行分享功能,多张...
  • 方法/步骤对于卡点视频或照片视频的制作,我们可以利用手机自带的相册所提供的相关功能来实现。如图所示,选择多张照片后,点击“创作”按钮。2.从弹出的扩展面板中选择“照片视频”项。3.此时就进入照片视频制作...
  • 工具:android studio目标:通过简单的相册制作,实现“瀑布流”效果,增加删除照片功能,熟悉RecyclerView的使用,菜单的使用,及适配器的制作。1.创建一个项目,并命名为PhotoManager。2.首先,我们需要在主界面...
  • fpv4 flash相册系统

    2012-03-11 10:16:49
    分类详细设置增加分类简介信息输入 更新XML后增加了一些返回链接 可以使用小图扩展信息后台控制选项 修正场景改变到某个大小时小图列表会超出边界的bug 改进大图中下方小图的鼠标停留控制 增加可设置默认为打开大图 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,378
精华内容 2,951
关键字:

如何设置自己的相册分类