1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.supportv7.graphics; 18 19 import com.example.android.supportv7.R; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.database.Cursor; 24 import android.graphics.Bitmap; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.provider.MediaStore; 28 import android.support.v4.app.ListFragment; 29 import android.support.v4.app.LoaderManager; 30 import android.support.v4.content.CursorLoader; 31 import android.support.v4.content.Loader; 32 import android.support.v4.widget.ResourceCursorAdapter; 33 import android.support.v7.app.ActionBarActivity; 34 import android.support.v7.graphics.Palette; 35 import android.view.Menu; 36 import android.view.MenuInflater; 37 import android.view.MenuItem; 38 import android.view.View; 39 import android.widget.ImageView; 40 import android.widget.ListView; 41 42 /** 43 * Activity which displays the images from the device's {@link MediaStore}, alongside the generated 44 * {@link android.support.v7.graphics.Palette} results. 45 * 46 * Allows the customization of the number of colors used in the palette generation, to demonstrate 47 * the difference in results for different types of images. 48 */ 49 public class PaletteActivity extends ActionBarActivity { 50 51 @Override 52 protected void onCreate(Bundle savedInstanceState) { 53 super.onCreate(savedInstanceState); 54 55 getSupportFragmentManager() 56 .beginTransaction() 57 .replace(android.R.id.content, new PaletteMediaStoreListFragment()) 58 .commit(); 59 } 60 61 /** 62 * The {@link android.support.v4.app.ListFragment} which does all of the hard work. 63 */ 64 public static class PaletteMediaStoreListFragment extends ListFragment 65 implements LoaderManager.LoaderCallbacks<Cursor> { 66 67 /** 68 * Projection used for querying the {@link android.provider.MediaStore}. 69 */ 70 static final String[] PROJECTION = { 71 MediaStore.Images.ImageColumns._ID, 72 MediaStore.Images.ImageColumns.DATE_ADDED 73 }; 74 75 private PhotosCursorAdapter mAdapter; 76 77 @Override 78 public void onCreate(Bundle savedInstanceState) { 79 super.onCreate(savedInstanceState); 80 setHasOptionsMenu(true); 81 } 82 83 @Override 84 public void onViewCreated(View view, Bundle savedInstanceState) { 85 super.onViewCreated(view, savedInstanceState); 86 87 // Enable fast scroll to make it easier to navigate large number of images 88 getListView().setFastScrollEnabled(true); 89 } 90 91 @Override 92 public void onActivityCreated(Bundle savedInstanceState) { 93 super.onActivityCreated(savedInstanceState); 94 95 // Create an Adapter and use a new Adapter 96 mAdapter = new PhotosCursorAdapter(getActivity(), null); 97 mAdapter.setNumColors(16); 98 setListAdapter(mAdapter); 99 100 // Start the loader manager to create our CursorLoader 101 getLoaderManager().initLoader(0, null, this); 102 } 103 104 @Override 105 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 106 inflater.inflate(R.menu.sample_palette_actions, menu); 107 } 108 109 @Override 110 public boolean onOptionsItemSelected(MenuItem item) { 111 switch (item.getItemId()) { 112 case R.id.menu_num_colors_8: 113 mAdapter.setNumColors(8); 114 item.setChecked(true); 115 return true; 116 case R.id.menu_num_colors_12: 117 mAdapter.setNumColors(12); 118 item.setChecked(true); 119 return true; 120 case R.id.menu_num_colors_16: 121 mAdapter.setNumColors(16); 122 item.setChecked(true); 123 return true; 124 case R.id.menu_num_colors_24: 125 mAdapter.setNumColors(24); 126 item.setChecked(true); 127 return true; 128 case R.id.menu_num_colors_32: 129 mAdapter.setNumColors(32); 130 item.setChecked(true); 131 return true; 132 } 133 134 return super.onOptionsItemSelected(item); 135 } 136 137 @Override 138 public void onListItemClick(ListView l, View v, int position, long id) { 139 final Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() 140 .appendEncodedPath(String.valueOf(id)).build(); 141 142 // Start the Detail Activity 143 Intent intent = new Intent(getActivity(), PaletteDetailActivity.class); 144 intent.setData(uri); 145 startActivity(intent); 146 } 147 148 @Override 149 public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { 150 return new CursorLoader( 151 getActivity(), 152 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 153 PROJECTION, 154 null, 155 null, 156 MediaStore.Images.ImageColumns.DATE_ADDED + " DESC"); 157 } 158 159 @Override 160 public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 161 mAdapter.swapCursor(cursor); 162 } 163 164 @Override 165 public void onLoaderReset(Loader<Cursor> cursorLoader) { 166 mAdapter.swapCursor(null); 167 } 168 169 private static class PhotosCursorAdapter extends ResourceCursorAdapter { 170 171 private int mNumColors; 172 173 public PhotosCursorAdapter(Context context, Cursor c) { 174 super(context, R.layout.palette_list_item, c, false); 175 mContext = context; 176 } 177 178 /** 179 * Set the number of colors used for {@link Palette} generation. 180 */ 181 void setNumColors(int numColors) { 182 mNumColors = numColors; 183 notifyDataSetChanged(); 184 } 185 186 @Override 187 public void bindView(final View view, Context context, Cursor cursor) { 188 // Let's reset the view, clearing the ImageView and resetting the background colors 189 // of the Palette UI 190 ImageView imageView = (ImageView) view.findViewById(R.id.image); 191 imageView.setImageDrawable(null); 192 193 view.findViewById(R.id.text_vibrant).setBackgroundDrawable(null); 194 view.findViewById(R.id.text_muted).setBackgroundDrawable(null); 195 view.findViewById(R.id.text_light_vibrant).setBackgroundDrawable(null); 196 view.findViewById(R.id.text_light_muted).setBackgroundDrawable(null); 197 view.findViewById(R.id.text_dark_vibrant).setBackgroundDrawable(null); 198 view.findViewById(R.id.text_dark_muted).setBackgroundDrawable(null); 199 200 final long id = cursor.getLong( 201 cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID)); 202 203 ImageLoader.loadMediaStoreThumbnail(imageView, id, new ImageLoader.Listener() { 204 @Override 205 public void onImageLoaded(Bitmap bitmap) { 206 Palette.generateAsync(bitmap, mNumColors, 207 new Palette.PaletteAsyncListener() { 208 @Override 209 public void onGenerated(Palette palette) { 210 setBackgroundColor( 211 view.findViewById(R.id.text_vibrant), 212 palette.getVibrantSwatch()); 213 setBackgroundColor( 214 view.findViewById(R.id.text_muted), 215 palette.getMutedSwatch()); 216 setBackgroundColor( 217 view.findViewById(R.id.text_light_vibrant), 218 palette.getLightVibrantSwatch()); 219 setBackgroundColor( 220 view.findViewById(R.id.text_light_muted), 221 palette.getLightMutedSwatch()); 222 setBackgroundColor( 223 view.findViewById(R.id.text_dark_vibrant), 224 palette.getDarkVibrantSwatch()); 225 setBackgroundColor( 226 view.findViewById(R.id.text_dark_muted), 227 palette.getDarkMutedSwatch()); 228 } 229 }); 230 } 231 }); 232 } 233 } 234 235 static void setBackgroundColor(View view, Palette.Swatch swatch) { 236 if (view != null && swatch != null) { 237 view.setBackgroundColor(swatch.getRgb()); 238 } 239 } 240 241 } 242 243 }