Back to project page Wardrobe_app.
The source code is released under:
Apache License
If you think the Android project Wardrobe_app listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright 2012 Google Inc./* w w w. j ava 2s .c o m*/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.busolo.apps.wardrobe.utils; import android.annotation.TargetApi; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; import android.text.TextUtils; import android.widget.ImageView; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.WeakReference; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import com.android.busolo.apps.wardrobe.engine.R; import static com.android.busolo.apps.wardrobe.utils.LogUtils.makeLogTag; import static com.android.busolo.apps.wardrobe.utils.LogUtils.LOGE; /** * An assortment of UI helpers. */ public class UIUtils { private static final String TAG = makeLogTag(UIUtils.class); public static final int ANIMATION_FADE_IN_TIME = 250; public static final String TRACK_ICONS_TAG = "tracks"; public static boolean isTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; } /** * Asynchronously load the track icon bitmap. To use, subclass and override * {@link #onPostExecute(android.graphics.Bitmap)} which passes in the generated track icon * bitmap. */ public static abstract class TrackIconAsyncTask extends AsyncTask<Context, Void, Bitmap> { private String mTrackName; private int mTrackColor; private BitmapCache mBitmapCache; public TrackIconAsyncTask(String trackName, int trackColor) { mTrackName = trackName; mTrackColor = trackColor; } public TrackIconAsyncTask(String trackName, int trackColor, BitmapCache bitmapCache) { mTrackName = trackName; mTrackColor = trackColor; mBitmapCache = bitmapCache; } @Override protected Bitmap doInBackground(Context... contexts) { Bitmap bitmap = getTrackIconSync(contexts[0], mTrackName, mTrackColor); // Store bitmap in memory cache for future use. if (bitmap != null && mBitmapCache != null) { mBitmapCache.addBitmapToCache(mTrackName, bitmap); } return bitmap; } protected abstract void onPostExecute(Bitmap bitmap); } /** * Synchronously get the track icon bitmap. Don't call this from the main thread, instead use either * {@link UIUtils.TrackIconAsyncTask} or {@link UIUtils.TrackIconViewAsyncTask} to * asynchronously load the track icon. */ public static Bitmap getTrackIconSync(Context ctx, String trackName, int trackColor) { if (TextUtils.isEmpty(trackName)) { return null; } // Find a suitable disk cache directory for the track icons and create if it doesn't // already exist. File outputDir = ImageLoader.getDiskCacheDir(ctx, TRACK_ICONS_TAG); if (!outputDir.exists()) { outputDir.mkdirs(); } // Generate a unique filename to store this track icon in using a hash function. File imageFile = new File(outputDir + File.separator + hashKeyForDisk(trackName)); Bitmap bitmap = null; // If file already exists and is readable, try and decode the bitmap from the disk. if (imageFile.exists() && imageFile.canRead()) { bitmap = BitmapFactory.decodeFile(imageFile.toString()); } // If bitmap is still null here the track icon was not found in the disk cache. if (bitmap == null) { // Create the icon using the provided track name and color. bitmap = UIUtils.createTrackIcon(ctx, trackName, trackColor); // Now write it out to disk for future use. BufferedOutputStream outputStream = null; try { outputStream = new BufferedOutputStream(new FileOutputStream(imageFile)); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); } catch (FileNotFoundException e) { LOGE(TAG, "TrackIconAsyncTask - unable to open file - " + e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException ignored) { } } } } return bitmap; } /** * Create the track icon bitmap. Don't call this directly, instead use either * {@link UIUtils.TrackIconAsyncTask} or {@link UIUtils.TrackIconViewAsyncTask} to * asynchronously load the track icon. */ private static Bitmap createTrackIcon(Context context, String trackName, int trackColor) { final Resources res = context.getResources(); int iconSize = res.getDimensionPixelSize(R.dimen.track_icon_source_size); Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(icon); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(trackColor); canvas.drawCircle(iconSize / 2, iconSize / 2, iconSize / 2, paint); int iconResId = res.getIdentifier( "track_" + ParserUtils.sanitizeId(trackName), "drawable", context.getPackageName()); if (iconResId != 0) { Drawable sourceIconDrawable = res.getDrawable(iconResId); sourceIconDrawable.setBounds(0, 0, iconSize, iconSize); sourceIconDrawable.draw(canvas); } return icon; } /** * A subclass of {@link TrackIconAsyncTask} that loads the generated track icon bitmap into * the provided {@link android.widget.ImageView}. This class also handles concurrency in the case the * ImageView is recycled (eg. in a ListView adapter) so that the incorrect image will not show * in a recycled view. */ public static class TrackIconViewAsyncTask extends TrackIconAsyncTask { private WeakReference<ImageView> mImageViewReference; public TrackIconViewAsyncTask(ImageView imageView, String trackName, int trackColor, BitmapCache bitmapCache) { super(trackName, trackColor, bitmapCache); // Store this AsyncTask in the tag of the ImageView so we can compare if the same task // is still running on this ImageView once processing is complete. This helps with // view recycling that takes place in a ListView type adapter. imageView.setTag(this); // If we have a BitmapCache, check if this track icon is available already. Bitmap bitmap = bitmapCache != null ? bitmapCache.getBitmapFromMemCache(trackName) : null; // If found in BitmapCache set the Bitmap directly and cancel the task. if (bitmap != null) { imageView.setImageBitmap(bitmap); cancel(true); } else { // Otherwise clear the ImageView and store a WeakReference for later use. Better // to use a WeakReference here in case the task runs long and the holding Activity // or Fragment goes away. imageView.setImageDrawable(null); mImageViewReference = new WeakReference<ImageView>(imageView); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected void onPostExecute(Bitmap bitmap) { ImageView imageView = mImageViewReference != null ? mImageViewReference.get() : null; // If ImageView is still around, bitmap processed OK and this task is not canceled. if (imageView != null && bitmap != null && !isCancelled()) { // Ensure this task is still the same one assigned to this ImageView, if not the // view was likely recycled and a new task with a different icon is now running // on the view and we shouldn't proceed. if (this.equals(imageView.getTag())) { // On HC-MR1 run a quick fade-in animation. if (hasHoneycombMR1()) { imageView.setAlpha(0f); imageView.setImageBitmap(bitmap); imageView.animate() .alpha(1f) .setDuration(ANIMATION_FADE_IN_TIME) .setListener(null); } else { // Before HC-MR1 set the Bitmap directly. imageView.setImageBitmap(bitmap); } } } } } /** * A hashing method that changes a string (like a URL) into a hash suitable for using as a * disk filename. */ private static String hashKeyForDisk(String key) { String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(key.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); } return cacheKey; } private static String bytesToHexString(byte[] bytes) { // http://stackoverflow.com/questions/332079 StringBuilder sb = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(0xFF & bytes[i]); if (hex.length() == 1) { sb.append('0'); } sb.append(hex); } return sb.toString(); } public static boolean hasHoneycomb() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; } public static boolean hasHoneycombMR1() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1; } public static boolean hasICS() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; } public static boolean hasJellyBeanMR1() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; } public static boolean isHoneycombTablet(Context context) { return hasHoneycomb() && isTablet(context); } }