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