Adding browsable prebuilt samples for march push
Change-Id: I952db10d9c9acb4940db08a07789347ea2effe4d
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.example.android.displayingbitmaps.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActionBar;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.android.displayingbitmaps.BuildConfig;
|
||||
import com.example.android.displayingbitmaps.R;
|
||||
import com.example.android.displayingbitmaps.provider.Images;
|
||||
import com.example.android.displayingbitmaps.util.ImageCache;
|
||||
import com.example.android.displayingbitmaps.util.ImageFetcher;
|
||||
import com.example.android.displayingbitmaps.util.Utils;
|
||||
|
||||
public class ImageDetailActivity extends FragmentActivity implements OnClickListener {
|
||||
private static final String IMAGE_CACHE_DIR = "images";
|
||||
public static final String EXTRA_IMAGE = "extra_image";
|
||||
|
||||
private ImagePagerAdapter mAdapter;
|
||||
private ImageFetcher mImageFetcher;
|
||||
private ViewPager mPager;
|
||||
|
||||
@TargetApi(VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.enableStrictMode();
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.image_detail_pager);
|
||||
|
||||
// Fetch screen height and width, to use as our max size when loading images as this
|
||||
// activity runs full screen
|
||||
final DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
final int height = displayMetrics.heightPixels;
|
||||
final int width = displayMetrics.widthPixels;
|
||||
|
||||
// For this sample we'll use half of the longest width to resize our images. As the
|
||||
// image scaling ensures the image is larger than this, we should be left with a
|
||||
// resolution that is appropriate for both portrait and landscape. For best image quality
|
||||
// we shouldn't divide by 2, but this will use more memory and require a larger memory
|
||||
// cache.
|
||||
final int longest = (height > width ? height : width) / 2;
|
||||
|
||||
ImageCache.ImageCacheParams cacheParams =
|
||||
new ImageCache.ImageCacheParams(this, IMAGE_CACHE_DIR);
|
||||
cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory
|
||||
|
||||
// The ImageFetcher takes care of loading images into our ImageView children asynchronously
|
||||
mImageFetcher = new ImageFetcher(this, longest);
|
||||
mImageFetcher.addImageCache(getSupportFragmentManager(), cacheParams);
|
||||
mImageFetcher.setImageFadeIn(false);
|
||||
|
||||
// Set up ViewPager and backing adapter
|
||||
mAdapter = new ImagePagerAdapter(getSupportFragmentManager(), Images.imageUrls.length);
|
||||
mPager = (ViewPager) findViewById(R.id.pager);
|
||||
mPager.setAdapter(mAdapter);
|
||||
mPager.setPageMargin((int) getResources().getDimension(R.dimen.horizontal_page_margin));
|
||||
mPager.setOffscreenPageLimit(2);
|
||||
|
||||
// Set up activity to go full screen
|
||||
getWindow().addFlags(LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
// Enable some additional newer visibility and ActionBar features to create a more
|
||||
// immersive photo viewing experience
|
||||
if (Utils.hasHoneycomb()) {
|
||||
final ActionBar actionBar = getActionBar();
|
||||
|
||||
// Hide title text and set home as up
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// Hide and show the ActionBar as the visibility changes
|
||||
mPager.setOnSystemUiVisibilityChangeListener(
|
||||
new View.OnSystemUiVisibilityChangeListener() {
|
||||
@Override
|
||||
public void onSystemUiVisibilityChange(int vis) {
|
||||
if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
|
||||
actionBar.hide();
|
||||
} else {
|
||||
actionBar.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start low profile mode and hide ActionBar
|
||||
mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
actionBar.hide();
|
||||
}
|
||||
|
||||
// Set the current item based on the extra passed in to this activity
|
||||
final int extraCurrentItem = getIntent().getIntExtra(EXTRA_IMAGE, -1);
|
||||
if (extraCurrentItem != -1) {
|
||||
mPager.setCurrentItem(extraCurrentItem);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mImageFetcher.setExitTasksEarly(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mImageFetcher.setExitTasksEarly(true);
|
||||
mImageFetcher.flushCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mImageFetcher.closeCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
NavUtils.navigateUpFromSameTask(this);
|
||||
return true;
|
||||
case R.id.clear_cache:
|
||||
mImageFetcher.clearCache();
|
||||
Toast.makeText(
|
||||
this, R.string.clear_cache_complete_toast,Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the ViewPager child fragments to load images via the one ImageFetcher
|
||||
*/
|
||||
public ImageFetcher getImageFetcher() {
|
||||
return mImageFetcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main adapter that backs the ViewPager. A subclass of FragmentStatePagerAdapter as there
|
||||
* could be a large number of items in the ViewPager and we don't want to retain them all in
|
||||
* memory at once but create/destroy them on the fly.
|
||||
*/
|
||||
private class ImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||
private final int mSize;
|
||||
|
||||
public ImagePagerAdapter(FragmentManager fm, int size) {
|
||||
super(fm);
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return ImageDetailFragment.newInstance(Images.imageUrls[position]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set on the ImageView in the ViewPager children fragments, to enable/disable low profile mode
|
||||
* when the ImageView is touched.
|
||||
*/
|
||||
@TargetApi(VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final int vis = mPager.getSystemUiVisibility();
|
||||
if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
|
||||
mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
} else {
|
||||
mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.example.android.displayingbitmaps.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.example.android.displayingbitmaps.R;
|
||||
import com.example.android.displayingbitmaps.util.ImageFetcher;
|
||||
import com.example.android.displayingbitmaps.util.ImageWorker;
|
||||
import com.example.android.displayingbitmaps.util.Utils;
|
||||
|
||||
/**
|
||||
* This fragment will populate the children of the ViewPager from {@link ImageDetailActivity}.
|
||||
*/
|
||||
public class ImageDetailFragment extends Fragment {
|
||||
private static final String IMAGE_DATA_EXTRA = "extra_image_data";
|
||||
private String mImageUrl;
|
||||
private ImageView mImageView;
|
||||
private ImageFetcher mImageFetcher;
|
||||
|
||||
/**
|
||||
* Factory method to generate a new instance of the fragment given an image number.
|
||||
*
|
||||
* @param imageUrl The image url to load
|
||||
* @return A new instance of ImageDetailFragment with imageNum extras
|
||||
*/
|
||||
public static ImageDetailFragment newInstance(String imageUrl) {
|
||||
final ImageDetailFragment f = new ImageDetailFragment();
|
||||
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(IMAGE_DATA_EXTRA, imageUrl);
|
||||
f.setArguments(args);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty constructor as per the Fragment documentation
|
||||
*/
|
||||
public ImageDetailFragment() {}
|
||||
|
||||
/**
|
||||
* Populate image using a url from extras, use the convenience factory method
|
||||
* {@link ImageDetailFragment#newInstance(String)} to create this fragment.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mImageUrl = getArguments() != null ? getArguments().getString(IMAGE_DATA_EXTRA) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate and locate the main ImageView
|
||||
final View v = inflater.inflate(R.layout.image_detail_fragment, container, false);
|
||||
mImageView = (ImageView) v.findViewById(R.id.imageView);
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
// Use the parent activity to load the image asynchronously into the ImageView (so a single
|
||||
// cache can be used over all pages in the ViewPager
|
||||
if (ImageDetailActivity.class.isInstance(getActivity())) {
|
||||
mImageFetcher = ((ImageDetailActivity) getActivity()).getImageFetcher();
|
||||
mImageFetcher.loadImage(mImageUrl, mImageView);
|
||||
}
|
||||
|
||||
// Pass clicks on the ImageView to the parent activity to handle
|
||||
if (OnClickListener.class.isInstance(getActivity()) && Utils.hasHoneycomb()) {
|
||||
mImageView.setOnClickListener((OnClickListener) getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mImageView != null) {
|
||||
// Cancel any pending image work
|
||||
ImageWorker.cancelWork(mImageView);
|
||||
mImageView.setImageDrawable(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.example.android.displayingbitmaps.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
import com.example.android.displayingbitmaps.BuildConfig;
|
||||
import com.example.android.displayingbitmaps.util.Utils;
|
||||
|
||||
/**
|
||||
* Simple FragmentActivity to hold the main {@link ImageGridFragment} and not much else.
|
||||
*/
|
||||
public class ImageGridActivity extends FragmentActivity {
|
||||
private static final String TAG = "ImageGridActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.enableStrictMode();
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getSupportFragmentManager().findFragmentByTag(TAG) == null) {
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.add(android.R.id.content, new ImageGridFragment(), TAG);
|
||||
ft.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.example.android.displayingbitmaps.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.android.common.logger.Log;
|
||||
import com.example.android.displayingbitmaps.BuildConfig;
|
||||
import com.example.android.displayingbitmaps.R;
|
||||
import com.example.android.displayingbitmaps.provider.Images;
|
||||
import com.example.android.displayingbitmaps.util.ImageCache;
|
||||
import com.example.android.displayingbitmaps.util.ImageFetcher;
|
||||
import com.example.android.displayingbitmaps.util.Utils;
|
||||
|
||||
/**
|
||||
* The main fragment that powers the ImageGridActivity screen. Fairly straight forward GridView
|
||||
* implementation with the key addition being the ImageWorker class w/ImageCache to load children
|
||||
* asynchronously, keeping the UI nice and smooth and caching thumbnails for quick retrieval. The
|
||||
* cache is retained over configuration changes like orientation change so the images are populated
|
||||
* quickly if, for example, the user rotates the device.
|
||||
*/
|
||||
public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {
|
||||
private static final String TAG = "ImageGridFragment";
|
||||
private static final String IMAGE_CACHE_DIR = "thumbs";
|
||||
|
||||
private int mImageThumbSize;
|
||||
private int mImageThumbSpacing;
|
||||
private ImageAdapter mAdapter;
|
||||
private ImageFetcher mImageFetcher;
|
||||
|
||||
/**
|
||||
* Empty constructor as per the Fragment documentation
|
||||
*/
|
||||
public ImageGridFragment() {}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
mImageThumbSize = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size);
|
||||
mImageThumbSpacing = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_spacing);
|
||||
|
||||
mAdapter = new ImageAdapter(getActivity());
|
||||
|
||||
ImageCache.ImageCacheParams cacheParams =
|
||||
new ImageCache.ImageCacheParams(getActivity(), IMAGE_CACHE_DIR);
|
||||
|
||||
cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory
|
||||
|
||||
// The ImageFetcher takes care of loading images into our ImageView children asynchronously
|
||||
mImageFetcher = new ImageFetcher(getActivity(), mImageThumbSize);
|
||||
mImageFetcher.setLoadingImage(R.drawable.empty_photo);
|
||||
mImageFetcher.addImageCache(getActivity().getSupportFragmentManager(), cacheParams);
|
||||
}
|
||||
|
||||
@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);
|
||||
mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
|
||||
// Pause fetcher to ensure smoother scrolling when flinging
|
||||
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
|
||||
// Before Honeycomb pause image loading on scroll to help with performance
|
||||
if (!Utils.hasHoneycomb()) {
|
||||
mImageFetcher.setPauseWork(true);
|
||||
}
|
||||
} else {
|
||||
mImageFetcher.setPauseWork(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView absListView, int firstVisibleItem,
|
||||
int visibleItemCount, int totalItemCount) {
|
||||
}
|
||||
});
|
||||
|
||||
// This listener is used to get the final width of the GridView and then calculate the
|
||||
// number of columns and the width of each column. The width of each column is variable
|
||||
// as the GridView has stretchMode=columnWidth. The column width is used to set the height
|
||||
// of each view so we get nice square thumbnails.
|
||||
mGridView.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (mAdapter.getNumColumns() == 0) {
|
||||
final int numColumns = (int) Math.floor(
|
||||
mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing));
|
||||
if (numColumns > 0) {
|
||||
final int columnWidth =
|
||||
(mGridView.getWidth() / numColumns) - mImageThumbSpacing;
|
||||
mAdapter.setNumColumns(numColumns);
|
||||
mAdapter.setItemHeight(columnWidth);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(TAG, "onCreateView - numColumns set to " + numColumns);
|
||||
}
|
||||
if (Utils.hasJellyBean()) {
|
||||
mGridView.getViewTreeObserver()
|
||||
.removeOnGlobalLayoutListener(this);
|
||||
} else {
|
||||
mGridView.getViewTreeObserver()
|
||||
.removeGlobalOnLayoutListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mImageFetcher.setExitTasksEarly(false);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mImageFetcher.setPauseWork(false);
|
||||
mImageFetcher.setExitTasksEarly(true);
|
||||
mImageFetcher.flushCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mImageFetcher.closeCache();
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
||||
@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, (int) id);
|
||||
if (Utils.hasJellyBean()) {
|
||||
// makeThumbnailScaleUpAnimation() looks kind of ugly here as the loading spinner may
|
||||
// show plus the thumbnail image in GridView is cropped. so using
|
||||
// makeScaleUpAnimation() instead.
|
||||
ActivityOptions options =
|
||||
ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight());
|
||||
getActivity().startActivity(i, options.toBundle());
|
||||
} else {
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.main_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.clear_cache:
|
||||
mImageFetcher.clearCache();
|
||||
Toast.makeText(getActivity(), R.string.clear_cache_complete_toast,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* The main adapter that backs the GridView. This is fairly standard except the number of
|
||||
* columns in the GridView is used to create a fake top row of empty views as we use a
|
||||
* transparent ActionBar and don't want the real top row of images to start off covered by it.
|
||||
*/
|
||||
private class ImageAdapter extends BaseAdapter {
|
||||
|
||||
private final Context mContext;
|
||||
private int mItemHeight = 0;
|
||||
private int mNumColumns = 0;
|
||||
private int mActionBarHeight = 0;
|
||||
private GridView.LayoutParams mImageViewLayoutParams;
|
||||
|
||||
public ImageAdapter(Context context) {
|
||||
super();
|
||||
mContext = context;
|
||||
mImageViewLayoutParams = new GridView.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
// Calculate ActionBar height
|
||||
TypedValue tv = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(
|
||||
android.R.attr.actionBarSize, tv, true)) {
|
||||
mActionBarHeight = TypedValue.complexToDimensionPixelSize(
|
||||
tv.data, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
// If columns have yet to be determined, return no items
|
||||
if (getNumColumns() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Size + number of columns for top empty row
|
||||
return Images.imageThumbUrls.length + mNumColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return position < mNumColumns ?
|
||||
null : Images.imageThumbUrls[position - mNumColumns];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position < mNumColumns ? 0 : position - mNumColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
// Two types of views, the normal ImageView and the top row of empty views
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return (position < mNumColumns) ? 1 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup container) {
|
||||
//BEGIN_INCLUDE(load_gridview_item)
|
||||
// First check if this is the top row
|
||||
if (position < mNumColumns) {
|
||||
if (convertView == null) {
|
||||
convertView = new View(mContext);
|
||||
}
|
||||
// Set empty view with height of ActionBar
|
||||
convertView.setLayoutParams(new AbsListView.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mActionBarHeight));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
// Now handle the main ImageView thumbnails
|
||||
ImageView imageView;
|
||||
if (convertView == null) { // if it's not recycled, instantiate and initialize
|
||||
imageView = new RecyclingImageView(mContext);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
imageView.setLayoutParams(mImageViewLayoutParams);
|
||||
} else { // Otherwise re-use the converted view
|
||||
imageView = (ImageView) convertView;
|
||||
}
|
||||
|
||||
// Check the height matches our calculated column width
|
||||
if (imageView.getLayoutParams().height != mItemHeight) {
|
||||
imageView.setLayoutParams(mImageViewLayoutParams);
|
||||
}
|
||||
|
||||
// Finally load the image asynchronously into the ImageView, this also takes care of
|
||||
// setting a placeholder image while the background thread runs
|
||||
mImageFetcher.loadImage(Images.imageThumbUrls[position - mNumColumns], imageView);
|
||||
return imageView;
|
||||
//END_INCLUDE(load_gridview_item)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item height. Useful for when we know the column width so the height can be set
|
||||
* to match.
|
||||
*
|
||||
* @param height
|
||||
*/
|
||||
public void setItemHeight(int height) {
|
||||
if (height == mItemHeight) {
|
||||
return;
|
||||
}
|
||||
mItemHeight = height;
|
||||
mImageViewLayoutParams =
|
||||
new GridView.LayoutParams(LayoutParams.MATCH_PARENT, mItemHeight);
|
||||
mImageFetcher.setImageSize(height);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setNumColumns(int numColumns) {
|
||||
mNumColumns = numColumns;
|
||||
}
|
||||
|
||||
public int getNumColumns() {
|
||||
return mNumColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* 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.example.android.displayingbitmaps.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.example.android.displayingbitmaps.util.RecyclingBitmapDrawable;
|
||||
|
||||
/**
|
||||
* Sub-class of ImageView which automatically notifies the drawable when it is
|
||||
* being displayed.
|
||||
*/
|
||||
public class RecyclingImageView extends ImageView {
|
||||
|
||||
public RecyclingImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RecyclingImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see android.widget.ImageView#onDetachedFromWindow()
|
||||
*/
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
// This has been detached from Window, so clear the drawable
|
||||
setImageDrawable(null);
|
||||
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
|
||||
*/
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
// Keep hold of previous Drawable
|
||||
final Drawable previousDrawable = getDrawable();
|
||||
|
||||
// Call super to set new Drawable
|
||||
super.setImageDrawable(drawable);
|
||||
|
||||
// Notify new Drawable that it is being displayed
|
||||
notifyDrawable(drawable, true);
|
||||
|
||||
// Notify old Drawable so it is no longer being displayed
|
||||
notifyDrawable(previousDrawable, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the drawable that it's displayed state has changed.
|
||||
*
|
||||
* @param drawable
|
||||
* @param isDisplayed
|
||||
*/
|
||||
private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
|
||||
if (drawable instanceof RecyclingBitmapDrawable) {
|
||||
// The drawable is a CountingBitmapDrawable, so notify it
|
||||
((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
|
||||
} else if (drawable instanceof LayerDrawable) {
|
||||
// The drawable is a LayerDrawable, so recurse on each layer
|
||||
LayerDrawable layerDrawable = (LayerDrawable) drawable;
|
||||
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
|
||||
notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user