• Aucun résultat trouvé

Load Bitmaps into a GridView Implementation

Dans le document 2. Building Your First App (Page 194-200)

The grid list building block is useful for showing image data sets and can be implemented using a GridView component in which many images can be on-screen at any one time and many more need to be ready to appear if the user scrolls up or down. When implementing this type of control, you must ensure the UI remains fluid, memory usage remains under control and concurrency is handled correctly (due to the way GridView recycles its children views).

To start with, here is a standard GridView implementation with ImageView children placed inside a Fragment. Again, this might seem like a perfectly reasonable approach, but what would make it better?

Displaying Bitmaps in Your UI

195

Content from developer.android.com/training/displaying-bitmaps/display-bitmap.html through their Creative Commons Attribution 2.5 license

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener { private ImageAdapter mAdapter;

// A static dataset to back the GridView adapter

public final static Integer[] imageResIds = new Integer[] {

R.drawable.sample_image_1, R.drawable.sample_image_2, R.drawable.sample_image_3, R.drawable.sample_image_4, R.drawable.sample_image_5, R.drawable.sample_image_6, R.drawable.sample_image_7, R.drawable.sample_image_8, R.drawable.sample_image_9};

// Empty constructor as per Fragment docs public ImageGridFragment() {}

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

mAdapter = new ImageAdapter(getActivity());

}

@Override

public View onCreateView(

LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.image_grid_fragment, container, false);

final GridView mGridView = (GridView) v.findViewById(R.id.gridView);

mGridView.setAdapter(mAdapter);

mGridView.setOnItemClickListener(this);

return v;

}

@Override

public void onItemClick(AdapterView<?> parent, View v, int position, long id) { final Intent i = new Intent(getActivity(), ImageDetailActivity.class);

i.putExtra(ImageDetailActivity.EXTRA_IMAGE, position);

startActivity(i);

}

private class ImageAdapter extends BaseAdapter { private final Context mContext;

public ImageAdapter(Context context) { super();

mContext = context;

}

@Override

public int getCount() { return imageResIds.length;

}

@Override

public Object getItem(int position) { return imageResIds[position];

}

@Override

public long getItemId(int position) { return position;

}

@Override

public View getView(int position, View convertView, ViewGroup container) {

Displaying Bitmaps in Your UI

196

Content from developer.android.com/training/displaying-bitmaps/display-bitmap.html through their Creative Commons Attribution 2.5 license

ImageView imageView;

if (convertView == null) { // if it's not recycled, initialize some attributes imageView = new ImageView(mContext);

imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

imageView.setLayoutParams(new GridView.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

} else {

imageView = (ImageView) convertView;

}

imageView.setImageResource(imageResIds[position]); // Load image into ImageView

return imageView;

} } }

Once again, the problem with this implementation is that the image is being set in the UI thread. While this may work for small, simple images (due to system resource loading and caching), if any additional processing needs to be done, your UI grinds to a halt.

The same asynchronous processing and caching methods from the previous section can be implemented here. However, you also need to wary of concurrency issues as the GridView recycles its children views.

To handle this, use the techniques discussed in the Processing Bitmaps Off the UI Thread lesson. Here is the updated solution:

Displaying Bitmaps in Your UI

197

Content from developer.android.com/training/displaying-bitmaps/display-bitmap.html through their Creative Commons Attribution 2.5 license

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener { ...

private class ImageAdapter extends BaseAdapter { ...

@Override

public View getView(int position, View convertView, ViewGroup container) { ...

loadBitmap(imageResIds[position], imageView) return imageView;

} }

public void loadBitmap(int resId, ImageView imageView) { if (cancelPotentialWork(resId, imageView)) {

final BitmapWorkerTask task = new BitmapWorkerTask(imageView);

final AsyncDrawable asyncDrawable =

new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);

imageView.setImageDrawable(asyncDrawable);

task.execute(resId);

} }

static class AsyncDrawable extends BitmapDrawable {

private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;

public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { super(res, bitmap);

bitmapWorkerTaskReference =

new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);

}

public BitmapWorkerTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get();

} }

public static boolean cancelPotentialWork(int data, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

if (bitmapWorkerTask != null) {

final int bitmapData = bitmapWorkerTask.data;

if (bitmapData != data) { // Cancel previous task bitmapWorkerTask.cancel(true);

} else {

// The same work is already in progress return false;

} }

// No task associated with the ImageView, or an existing task was cancelled return true;

}

private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) {

final Drawable drawable = imageView.getDrawable();

if (drawable instanceof AsyncDrawable) {

Displaying Bitmaps in Your UI

198

Content from developer.android.com/training/displaying-bitmaps/display-bitmap.html through their Creative Commons Attribution 2.5 license

final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;

return asyncDrawable.getBitmapWorkerTask();

} }

return null;

}

... // include updated BitmapWorkerTask class

Note: The same code can easily be adapted to work with ListView as well.

This implementation allows for flexibility in how the images are processed and loaded without impeding the smoothness of the UI. In the background task you can load images from the network or resize large digital camera photos and the images appear as the tasks finish processing.

For a full example of this and other concepts discussed in this lesson, please see the included sample application.

Displaying Graphics with OpenGL ES

199

Content from developer.android.com/training/graphics/opengl/index.html through their Creative Commons Attribution 2.5 license

66. Displaying Graphics with OpenGL ES

Content from developer.android.com/training/graphics/opengl/index.html through their Creative Commons Attribution 2.5 license

The Android framework provides plenty of standard tools for creating attractive, functional graphical user interfaces. However, if you want more control of what your application draws on screen, or are venturing into three dimensional graphics, you need to use a different tool. The OpenGL ES APIs provided by the Android framework offers a set of tools for displaying high-end, animated graphics that are limited only by your imagination and can also benefit from the acceleration of graphics processing units (GPUs) provided on many Android devices.

This class walks you through the basics of developing applications that use OpenGL, including setup, drawing objects, moving drawn elements and responding to touch input.

The example code in this class uses the OpenGL ES 2.0 APIs, which is the recommended API version to use with current Android devices. For more information about versions of OpenGL ES, see the OpenGL developer guide.

Note: Be careful not to mix OpenGL ES 1.x API calls with OpenGL ES 2.0 methods! The two APIs are not interchangeable and trying to use them together only results in frustration and sadness.

Lessons

Building an OpenGL ES Environment

Learn how to set up an Android application to be able to draw OpenGL graphics.

Defining Shapes

Learn how to define shapes and why you need to know about faces and winding.

Drawing Shapes

Learn how to draw OpenGL shapes in your application.

Applying Projection and Camera Views

Learn how to use projection and camera views to get a new perspective on your drawn objects.

Adding Motion

Learn how to do basic movement and animation of drawn objects with OpenGL.

Responding to Touch Events

Learn how to do basic interaction with OpenGL graphics.

Dependencies and prerequisites

• Android 2.2 (API Level 8) or higher

• Experience building an Android app You should also read

OpenGL Try it out

Download the sample OpenGLES.zip

Building an OpenGL ES Environment

200

Content from developer.android.com/training/graphics/opengl/environment.html through their Creative Commons Attribution 2.5 license

67. Building an OpenGL ES Environment

Content from developer.android.com/training/graphics/opengl/environment.html through their Creative Commons Attribution 2.5 license

In order to draw graphics with OpenGL ES in your Android application, you must create a view container for them. One of the more straight-forward ways to do this is to implement both a GLSurfaceView and a

GLSurfaceView.Renderer. A

GLSurfaceView is a view container for graphics drawn with OpenGL and

GLSurfaceView.Renderer controls what is drawn within that view. For more information about these classes, see the OpenGL ES developer guide.

GLSurfaceView is just one way to incorporate OpenGL ES graphics into your application. For a full-screen or near-full screen graphics view, it is a reasonable choice. Developers who want to incorporate OpenGL ES graphics in a small

portion of their layouts should take a look at TextureView. For real, do-it-yourself developers, it is also possible to build up an OpenGL ES view using SurfaceView, but this requires writing quite a bit of additional code.

This lesson explains how to complete a minimal implementation of GLSurfaceView and GLSurfaceView.Renderer in a simple application activity.

Dans le document 2. Building Your First App (Page 194-200)