How to implement image gallery (local images)

I am currently creating an application to display images from an SD card. Basically you make an album and add pictures to it, whether from the MediaStore collector’s camera.

I tried to implement 2 methods:

  • Standard gallery app with custom BaseAdapter to return view
  • Viewer with custom PagerAdapter

I do not want to display the grid view, so it should immediately go into full screen mode. After that, I want to disable scrolling left and right and only listen for clicks.

Atm both methods work in portrait mode. When I switch to landscape, some images just drop

03-20 12:20:56.515: W/OpenGLRenderer(17398): Bitmap too large to be uploaded into a texture 

and then memory errors. Stack overflow, if it is full of problems with OOM and gallery, you should rework the views to make them work, because convertView is always null in getView from BaseAdapter.

So, I used recycler for views, I limit it to 2 views and portrait mode working on method 1 (using the gallery). The landscape still gives me the same problem.

For method 2 (viewflipper) it processes the views

 @Override public void destroyItem(ViewGroup container, int position, Object object) { 

This is never called btw ... However, portrait mode works here. The landscape is still falling.

My raster image acquisition method:

 public static Bitmap getBitmap(Context ctx, int imageId, ImageView target) { String file = getPath(ctx, imageId); BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(file, bmOptions); WindowManager mgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); int scaleFactor = 1; if (mgr != null) { // Get the dimensions of the View int targetW = mgr.getDefaultDisplay().getWidth(); int targetH = mgr.getDefaultDisplay().getHeight(); Log.d(TAG, "Image width + height=" + targetW + "," + targetH); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image scaleFactor = Math.min(photoW / targetW, photoH / targetH); } else { Log.d(TAG, "Target is null"); } // Get the dimensions of the bitmap // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; logHeap(ImageHelper.class); Bitmap bm = BitmapFactory.decodeFile(file, bmOptions); if (target != null) { target.setImageBitmap(bm); } return bm; } 

It works well, I know that I use the window manager to get the screen, but that is because my ImageView still has a size (0,0) when I inflate it. Subsequently i call

 imgView.setLayoutParams(new Gallery.LayoutParams( Gallery.LayoutParams.FILL_PARENT, Gallery.LayoutParams.FILL_PARENT)); imgView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 

Nothing works ...

Please note that I do not use drawables or any other resources included in the APK. This gallery should be able to download images from an SD card or camera no matter what quality they were made. Obviously, the gallery should be able to process as many images as there are in the catalog.

Can someone please help me with the following questions?

  • Is there a way to make the default gallery right away in full screen and lock the grid? Thus, I only need an adapter to provide images instead of creating my own views. (perhaps this fixes OOM crashes).
  • Is my bitmap decoding function ok? Do I need to create some kind of hacks to catch landscape changes?
  • What is the best way to make the gallery I need using a viewer or gallery?
  • Does anyone have an example full-screen gallery code that doesn't crash?
+4
source share
1 answer

This is a problem that I have encountered several times in the past. Google has indeed published an article about this.

The problem is inSampleSize, which is used to decode the image. Since different devices have different screens and memory sizes (VM heap sizes that can range from 12 to 64 or more MB), you cannot decode images the same in all of them. For example, an image in a 320x240 device with 12 MB of memory should have the inSampleSize parameter set, while a 1280x720 64Mb memory heap device should use another inSampleSize (larger).

In the article I attack, an effective way of visualizing images for a given height and width is shown. Pay particular attention to the last code segment, they “open” the file first and compute inSampleSize for “full decoding” later.

I would also like to add these recommendations.

  • Use the getBitmap function using the async method, call a new thread or asyncTask (this is done because using SD takes time, and this will cause your application to freeze, a slow and bad impression on low and medium devices.

  • Try to always use the same Bitmap object. Avoid creating multiple "Bitmap bitmap = new Bitmap ()". You must understand that the loaded bitmaps are stored in memory and once assigned to be “harder” for the garbage collector to receive them.

  • When you have finished using Bitmap, set it to zero. This is from this, imagine that you have 12 MB of RAM. your application uses 8Mb now. The garbage collector starts up and cannot receive more unused RAM. you 10 bitmaps fast never make them null after assigning imageview data and somehow you save their link. It is assumed that each bitmap accepts a 500Kb Frame, on which your application will crash. Always use Bitmaps null after use.

  • Finally, use the DDMS provided in the google platform tools (you can access it using eclipse for debugging and see your memory usage, you can also make the Garbage Collection see how your application behaves).

+1
source

Source: https://habr.com/ru/post/1402423/


All Articles