Java tutorial
/* * Copyright (C) 2012 Andrew Neal 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.guayaba.tapir.ui.fragments; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.GridView; import com.guayaba.tapir.R; import com.guayaba.tapir.recycler.RecycleHolder; import com.guayaba.tapir.ui.MusicHolder; import com.guayaba.tapir.utils.ThemeUtils; import com.devspark.appmsg.AppMsg; import java.util.List; /** * Used to show all of the available themes on a user's device. * * @author Andrew Neal (andrewdneal@gmail.com) */ public class ThemeFragment extends Fragment implements OnItemClickListener { private static final int OPEN_IN_PLAY_STORE = 0; private GridView mGridView; private PackageManager mPackageManager; private List<ResolveInfo> mThemes; private String[] mEntries; private String[] mValues; private Drawable[] mThemePreview; private Resources mThemeResources; private String mThemePackageName; private String mThemeName; private ThemesAdapter mAdapter; private ThemeUtils mTheme; /** * Empty constructor as per the {@link Fragment} documentation */ public ThemeFragment() { } /** * {@inheritDoc} */ @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { // The View for the fragment's UI final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.grid_base, null); // Initialize the grid mGridView = (GridView) rootView.findViewById(R.id.grid_base); // Release any reference to the recycled Views mGridView.setRecyclerListener(new RecycleHolder()); // Set the new theme mGridView.setOnItemClickListener(this); // Listen for ContextMenus to be created mGridView.setOnCreateContextMenuListener(this); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // Limit the columns to one in portrait mode mGridView.setNumColumns(1); } else { // And two for landscape mGridView.setNumColumns(2); } return rootView; } /** * {@inheritDoc} */ @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); final Intent apolloThemeIntent = new Intent("com.guayaba.tapir.THEMES"); apolloThemeIntent.addCategory("android.intent.category.DEFAULT"); mPackageManager = getActivity().getPackageManager(); mThemes = mPackageManager.queryIntentActivities(apolloThemeIntent, 0); mEntries = new String[mThemes.size() + 1]; mValues = new String[mThemes.size() + 1]; mThemePreview = new Drawable[mThemes.size() + 1]; // Default items mEntries[0] = getString(R.string.app_name); // mValues[0] = ThemeUtils.APOLLO_PACKAGE; mThemePreview[0] = getResources().getDrawable(R.drawable.theme_preview); for (int i = 0; i < mThemes.size(); i++) { mThemePackageName = mThemes.get(i).activityInfo.packageName.toString(); mThemeName = mThemes.get(i).loadLabel(mPackageManager).toString(); mEntries[i + 1] = mThemeName; mValues[i + 1] = mThemePackageName; // Theme resources try { mThemeResources = mPackageManager.getResourcesForApplication(mThemePackageName.toString()); } catch (final NameNotFoundException ignored) { } // Theme preview final int previewId = mThemeResources.getIdentifier("theme_preview", "drawable", //$NON-NLS-2$ mThemePackageName.toString()); if (previewId != 0) { mThemePreview[i + 1] = mThemeResources.getDrawable(previewId); } } // Initialize the Adapter mAdapter = new ThemesAdapter(getActivity(), R.layout.fragment_themes_base); // Bind the data mGridView.setAdapter(mAdapter); // Get the theme utils mTheme = new ThemeUtils(getActivity()); } /** * {@inheritDoc} */ @Override public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) { final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; if (info.position > 0) { // Open to the theme's Play Store page menu.add(Menu.NONE, OPEN_IN_PLAY_STORE, Menu.NONE, getString(R.string.context_menu_open_in_play_store)); } super.onCreateContextMenu(menu, v, menuInfo); } /** * {@inheritDoc} */ @Override public boolean onContextItemSelected(final android.view.MenuItem item) { final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); switch (item.getItemId()) { case OPEN_IN_PLAY_STORE: ThemeUtils.openAppPage(getActivity(), mValues[info.position]); return true; default: break; } return super.onContextItemSelected(item); } /** * {@inheritDoc} */ @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { mTheme.setThemePackageName(mValues[position]); AppMsg.makeText(getActivity(), getString(R.string.theme_set, mEntries[position]), AppMsg.STYLE_CONFIRM) .show(); } /** * Populates the {@link GridView} with the available themes */ private class ThemesAdapter extends ArrayAdapter<ResolveInfo> { /** * Number of views (ImageView and TextView) */ private static final int VIEW_TYPE_COUNT = 2; /** * The resource ID of the layout to inflate */ private final int mLayoutID; /** * Used to cache the theme info */ private DataHolder[] mData; /** * Constructor of <code>ThemesAdapter</code> * * @param context The {@link Context} to use. * @param layoutID The resource ID of the view to inflate. */ public ThemesAdapter(final Context context, final int layoutID) { super(context, 0); // Get the layout ID mLayoutID = layoutID; // Build the cache buildCache(); } /** * {@inheritDoc} */ @Override public int getCount() { return mEntries.length; } /** * {@inheritDoc} */ @Override public View getView(final int position, View convertView, final ViewGroup parent) { /* Recycle ViewHolder's items */ MusicHolder holder; if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(mLayoutID, parent, false); holder = new MusicHolder(convertView); convertView.setTag(holder); } else { holder = (MusicHolder) convertView.getTag(); } // Retrieve the data holder final DataHolder dataHolder = mData[position]; // Set the theme preview holder.mImage.get().setImageDrawable(dataHolder.mPreview); // Set the theme name holder.mLineOne.get().setText(dataHolder.mName); return convertView; } /** * {@inheritDoc} */ @Override public boolean hasStableIds() { return true; } /** * {@inheritDoc} */ @Override public int getViewTypeCount() { return VIEW_TYPE_COUNT; } /** * Method used to cache the data used to populate the list or grid. The * idea is to cache everything before * {@code #getView(int, View, ViewGroup)} is called. */ private void buildCache() { mData = new DataHolder[getCount()]; for (int i = 0; i < getCount(); i++) { // Build the data holder mData[i] = new DataHolder(); // Theme names (line one) mData[i].mName = mEntries[i]; // Theme preview mData[i].mPreview = mThemePreview[i]; } } } /** * @param view The {@link View} used to initialize content */ public final static class DataHolder { public String mName; public Drawable mPreview; /** * Constructor of <code>DataHolder</code> */ public DataHolder() { super(); } } }