您的位置:首页 > 编程语言 > Go语言

ActionBar Goole官方例子-HoneyCombGallery

2014-02-27 16:20 225 查看
例子源码

MainActivity:

package com.example.android.hcgallery;

/** This is the main "launcher" activity.
* When running on a "large" or larger screen, this activity displays both the
* TitlesFragments and the Content Fragment. When on a smaller screen size, this
* activity displays only the TitlesFragment. In which case, selecting a list
* item opens the ContentActivity, holds only the ContentFragment. */
public class MainActivity extends Activity implements TitlesFragment.OnItemSelectedListener {

private Animator mCurrentTitlesAnimator;
private String[] mToggleLabels = {"Show Titles", "Hide Titles"};
private static final int NOTIFICATION_DEFAULT = 1;
private static final String ACTION_DIALOG = "com.example.android.hcgallery.action.DIALOG";
private int mThemeId = -1;
private boolean mDualFragments = false;
private boolean mTitlesHidden = false;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if(savedInstanceState != null) {
if (savedInstanceState.getInt("theme", -1) != -1) {
mThemeId = savedInstanceState.getInt("theme");
this.setTheme(mThemeId);
}
mTitlesHidden = savedInstanceState.getBoolean("titlesHidden");
}

setContentView(R.layout.main);

ActionBar bar = getActionBar();
bar.setDisplayShowTitleEnabled(false);

ContentFragment frag = (ContentFragment) getFragmentManager()
.findFragmentById(R.id.content_frag);
if (frag != null) mDualFragments = true;

if (mTitlesHidden) {
getFragmentManager().beginTransaction()
.hide(getFragmentManager().findFragmentById(R.id.titles_frag)).commit();
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
// If the device doesn't support camera, remove the camera menu item
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
menu.removeItem(R.id.menu_camera);
}
return true;
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If not showing both fragments, remove the "toggle titles" menu item
if (!mDualFragments) {
menu.removeItem(R.id.menu_toggleTitles);
} else {
menu.findItem(R.id.menu_toggleTitles).setTitle(mToggleLabels[mTitlesHidden ? 0 : 1]);
}
return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_camera:
Intent intent = new Intent(this, CameraActivity.class);
intent.putExtra("theme", mThemeId);
startActivity(intent);
return true;

case R.id.menu_toggleTitles:
toggleVisibleTitles();
return true;

case R.id.menu_toggleTheme:
if (mThemeId == R.style.AppTheme_Dark) {
mThemeId = R.style.AppTheme_Light;
} else {
mThemeId = R.style.AppTheme_Dark;
}
this.recreate();
return true;

case R.id.menu_showDialog:
showDialog("This is indeed an awesome dialog.");
return true;

case R.id.menu_showStandardNotification:
showNotification(false);
return true;

case R.id.menu_showCustomNotification:
showNotification(true);
return true;

default:
return super.onOptionsItemSelected(item);
}
}

/** Respond to the "toogle titles" item in the action bar */
public void toggleVisibleTitles() {
// Use these for custom animations.
final FragmentManager fm = getFragmentManager();
final TitlesFragment f = (TitlesFragment) fm
.findFragmentById(R.id.titles_frag);
final View titlesView = f.getView();

// Determine if we're in portrait, and whether we're showing or hiding the titles
// with this toggle.
final boolean isPortrait = getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT;

final boolean shouldShow = f.isHidden() || mCurrentTitlesAnimator != null;

// Cancel the current titles animation if there is one.
if (mCurrentTitlesAnimator != null)
mCurrentTitlesAnimator.cancel();

// Begin setting up the object animator. We'll animate the bottom or right edge of the
// titles view, as well as its alpha for a fade effect.
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(
titlesView,
PropertyValuesHolder.ofInt(
isPortrait ? "bottom" : "right",
shouldShow ? getResources().getDimensionPixelSize(R.dimen.titles_size)
: 0),
PropertyValuesHolder.ofFloat("alpha", shouldShow ? 1 : 0)
);

// At each step of the animation, we'll perform layout by calling setLayoutParams.
final ViewGroup.LayoutParams lp = titlesView.getLayoutParams();
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// *** WARNING ***: triggering layout at each animation frame highly impacts
// performance so you should only do this for simple layouts. More complicated
// layouts can be better served with individual animations on child views to
// avoid the performance penalty of layout.
if (isPortrait) {
lp.height = (Integer) valueAnimator.getAnimatedValue();
} else {
lp.width = (Integer) valueAnimator.getAnimatedValue();
}
titlesView.setLayoutParams(lp);
}
});

if (shouldShow) {
fm.beginTransaction().show(f).commit();
objectAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
mCurrentTitlesAnimator = null;
mTitlesHidden = false;
invalidateOptionsMenu();
}
});

} else {
objectAnimator.addListener(new AnimatorListenerAdapter() {
boolean canceled;

@Override
public void onAnimationCancel(Animator animation) {
canceled = true;
super.onAnimationCancel(animation);
}

@Override
public void onAnimationEnd(Animator animator) {
if (canceled)
return;
mCurrentTitlesAnimator = null;
fm.beginTransaction().hide(f).commit();
mTitlesHidden = true;
invalidateOptionsMenu();
}
});
}

// Start the animation.
objectAnimator.start();
mCurrentTitlesAnimator = objectAnimator;

// Manually trigger onNewIntent to check for ACTION_DIALOG.
onNewIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
if (ACTION_DIALOG.equals(intent.getAction())) {
showDialog(intent.getStringExtra(Intent.EXTRA_TEXT));
}
}

void showDialog(String text) {
// DialogFragment.show() will take care of adding the fragment
// in a transaction.  We also want to remove any currently showing
// dialog, so make our own transaction and take care of that here.
FragmentTransaction ft = getFragmentManager().beginTransaction();

DialogFragment newFragment = MyDialogFragment.newInstance(text);

// Show the dialog.
newFragment.show(ft, "dialog");
}

void showNotification(boolean custom) {
final Resources res = getResources();
final NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);

Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notify_example)
.setAutoCancel(true)
.setTicker(getString(R.string.notification_text))
.setContentIntent(getDialogPendingIntent("Tapped the notification entry."));

if (custom) {
// Sets a custom content view for the notification, including an image button.
RemoteViews layout = new RemoteViews(getPackageName(), R.layout.notification);
layout.setTextViewText(R.id.notification_title, getString(R.string.app_name));
layout.setOnClickPendingIntent(R.id.notification_button,
getDialogPendingIntent("Tapped the 'dialog' button in the notification."));
builder.setContent(layout);

// Notifications in Android 3.0 now have a standard mechanism for displaying large
// bitmaps such as contact avatars. Here, we load an example image and resize it to the
// appropriate size for large bitmaps in notifications.
Bitmap largeIconTemp = BitmapFactory.decodeResource(res,
R.drawable.notification_default_largeicon);
Bitmap largeIcon = Bitmap.createScaledBitmap(
largeIconTemp,
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height),
false);
largeIconTemp.recycle();

builder.setLargeIcon(largeIcon);

} else {
builder
.setNumber(7) // An example number.
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.notification_text));
}

notificationManager.notify(NOTIFICATION_DEFAULT, builder.getNotification());
}

PendingIntent getDialogPendingIntent(String dialogText) {
return PendingIntent.getActivity(
this,
dialogText.hashCode(), // Otherwise previous PendingIntents with the same
// requestCode may be overwritten.
new Intent(ACTION_DIALOG)
.putExtra(Intent.EXTRA_TEXT, dialogText)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
0);
}

@Override
public void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("theme", mThemeId);
outState.putBoolean("titlesHidden", mTitlesHidden);
}

/** Implementation for TitlesFragment.OnItemSelectedListener.
* When the TitlesFragment receives an onclick event for a list item,
* it's passed back to this activity through this method so that we can
* deliver it to the ContentFragment in the manner appropriate */
public void onItemSelected(int category, int position) {
if (!mDualFragments) {
// If showing only the TitlesFragment, start the ContentActivity and
// pass it the info about the selected item
Intent intent = new Intent(this, ContentActivity.class);
intent.putExtra("category", category);
intent.putExtra("position", position);
intent.putExtra("theme", mThemeId);
startActivity(intent);
} else {
// If showing both fragments, directly update the ContentFragment
ContentFragment frag = (ContentFragment) getFragmentManager()
.findFragmentById(R.id.content_frag);
frag.updateContentAndRecycleBitmap(category, position);
}
}

/** Dialog implementation that shows a simple dialog as a fragment */
public static class MyDialogFragment extends DialogFragment {

public static MyDialogFragment newInstance(String title) {
MyDialogFragment frag = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("text", title);
frag.setArguments(args);
return frag;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String text = getArguments().getString("text");

return new AlertDialog.Builder(getActivity())
.setTitle("A Dialog of Awesome")
.setMessage(text)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}
)
.create();
}
}
}

public class CameraActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
int themeId = this.getIntent().getExtras().getInt("theme");
this.setTheme(themeId);
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_sample);
}

}

public class CameraFragment extends Fragment {

private Preview mPreview;
Camera mCamera;
int mNumberOfCameras;
int mCurrentCamera;  // Camera ID currently chosen
int mCameraCurrentlyLocked;  // Camera ID that's actually acquired

// The first rear facing camera
int mDefaultCameraId;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Create a container that will hold a SurfaceView for camera previews
mPreview = new Preview(this.getActivity());

// Find the total number of cameras available
mNumberOfCameras = Camera.getNumberOfCameras();

// Find the ID of the rear-facing ("default") camera
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < mNumberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
mCurrentCamera = mDefaultCameraId = i;
}
}
setHasOptionsMenu(mNumberOfCameras > 1);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Add an up arrow to the "home" button, indicating that the button will go "up"
// one activity in the app's Activity heirarchy.
// Calls to getActionBar() aren't guaranteed to return the ActionBar when called
// from within the Fragment's onCreate method, because the Window's decor hasn't been
// initialized yet.  Either call for the ActionBar reference in Activity.onCreate()
// (after the setContentView(...) call), or in the Fragment's onActivityCreated method.
Activity activity = this.getActivity();
ActionBar actionBar = activity.getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return mPreview;
}

@Override
public void onResume() {
super.onResume();

// Use mCurrentCamera to select the camera desired to safely restore
// the fragment after the camera has been changed
mCamera = Camera.open(mCurrentCamera);
mCameraCurrentlyLocked = mCurrentCamera;
mPreview.setCamera(mCamera);
}

@Override
public void onPause() {
super.onPause();

// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.release();
mCamera = null;
}
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mNumberOfCameras > 1) {
// Inflate our menu which can gather user input for switching camera
inflater.inflate(R.menu.camera_menu, menu);
} else {
super.onCreateOptionsMenu(menu, inflater);
}
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.menu_switch_cam:
// Release this camera -> mCameraCurrentlyLocked
if (mCamera != null) {
mCamera.stopPreview();
mPreview.setCamera(null);
mCamera.release();
mCamera = null;
}

// Acquire the next camera and request Preview to reconfigure
// parameters.
mCurrentCamera = (mCameraCurrentlyLocked + 1) % mNumberOfCameras;
mCamera = Camera.open(mCurrentCamera);
mCameraCurrentlyLocked = mCurrentCamera;
mPreview.switchCamera(mCamera);

// Start the preview
mCamera.startPreview();
return true;
case android.R.id.home:
Intent intent = new Intent(this.getActivity(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
return true;

default:
return super.onOptionsItemSelected(item);
}
}
}

// ----------------------------------------------------------------------

/**
* A simple wrapper around a Camera and a SurfaceView that renders a centered
* preview of the Camera to the surface. We need to center the SurfaceView
* because not all devices have cameras that support preview sizes at the same
* aspect ratio as the device's display.
*/
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";

SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
boolean mSurfaceCreated = false;

Preview(Context context) {
super(context);

mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);

// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters()
.getSupportedPreviewSizes();
if (mSurfaceCreated) requestLayout();
}
}

public void switchCamera(Camera camera) {
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);

if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
height);
}

if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

mCamera.setParameters(parameters);
}
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (getChildCount() > 0) {
final View child = getChildAt(0);

final int width = r - l;
final int height = b - t;

int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}

// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height
/ previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width
/ previewWidth;
child.layout(0, (height - scaledChildHeight) / 2, width,
(height + scaledChildHeight) / 2);
}
}
}

public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
if (mPreviewSize == null) requestLayout();
mSurfaceCreated = true;
}

public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.stopPreview();
}
}

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null)
return null;

Size optimalSize = null;
double minDiff = Double.MAX_VALUE;

int targetHeight = h;

// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}

// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();

mCamera.setParameters(parameters);
mCamera.startPreview();
}

}


public class ContentActivity extends Activity {
private int mThemeId = 0;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Bundle extras = getIntent().getExtras();
if (extras != null) {
// The activity theme is the only state data that the activity needs
// to restore. All info about the content displayed is managed by the fragment
mThemeId = extras.getInt("theme");
} else if (savedInstanceState != null) {
// If there's no restore state, get the theme from the intent
mThemeId = savedInstanceState.getInt("theme");
}

if (mThemeId != 0) {
setTheme(mThemeId);
}

setContentView(R.layout.content_activity);

if (extras != null) {
// Take the info from the intent and deliver it to the fragment so it can update
int category = extras.getInt("category");
int position = extras.getInt("position");
ContentFragment frag = (ContentFragment) getFragmentManager().findFragmentById(R.id.content_frag);
frag.updateContentAndRecycleBitmap(category, position);
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("theme", mThemeId);
}
}

public class ContentFragment extends Fragment {
private View mContentView;
private int mCategory = 0;
private int mCurPosition = 0;
private boolean mSystemUiVisible = true;
private boolean mSoloFragment = false;

// The bitmap currently used by ImageView
private Bitmap mBitmap = null;

// Current action mode (contextual action bar, a.k.a. CAB)
private ActionMode mCurrentActionMode;

/** This is where we initialize the fragment's UI and attach some
* event listeners to UI components.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mContentView = inflater.inflate(R.layout.content_welcome, null);
final ImageView imageView = (ImageView) mContentView.findViewById(R.id.image);
mContentView.setDrawingCacheEnabled(false);

// Handle drag events when a list item is dragged into the view
mContentView.setOnDragListener(new View.OnDragListener() {
public boolean onDrag(View view, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_ENTERED:
view.setBackgroundColor(
getResources().getColor(R.color.drag_active_color));
break;

case DragEvent.ACTION_DRAG_EXITED:
view.setBackgroundColor(Color.TRANSPARENT);
break;

case DragEvent.ACTION_DRAG_STARTED:
return processDragStarted(event);

case DragEvent.ACTION_DROP:
view.setBackgroundColor(Color.TRANSPARENT);
return processDrop(event, imageView);
}
return false;
}
});

// Show/hide the system status bar when single-clicking a photo.
mContentView.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
if (mCurrentActionMode != null) {
// If we're in an action mode, don't toggle the action bar
return;
}

if (mSystemUiVisible) {
setSystemUiVisible(false);
} else {
setSystemUiVisible(true);
}
}
});

// When long-pressing a photo, activate the action mode for selection, showing the
// contextual action bar (CAB).
mContentView.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View view) {
if (mCurrentActionMode != null) {
return false;
}

mCurrentActionMode = getActivity().startActionMode(
mContentSelectionActionModeCallback);
view.setSelected(true);
return true;
}
});

return mContentView;
}

/** This is where we perform additional setup for the fragment that's either
* not related to the fragment's layout or must be done after the layout is drawn.
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

// Set member variable for whether this fragment is the only one in the activity
Fragment listFragment = getFragmentManager().findFragmentById(R.id.titles_frag);
mSoloFragment = listFragment == null ? true : false;

if (mSoloFragment) {
// The fragment is alone, so enable up navigation
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
// Must call in order to get callback to onOptionsItemSelected()
setHasOptionsMenu(true);
}

// Current position and UI visibility should survive screen rotations.
if (savedInstanceState != null) {
setSystemUiVisible(savedInstanceState.getBoolean("systemUiVisible"));
if (mSoloFragment) {
// Restoring these members is not necessary when this fragment
// is combined with the TitlesFragment, because when the TitlesFragment
// is restored, it selects the appropriate item and sends the event
// to the updateContentAndRecycleBitmap() method itself
mCategory = savedInstanceState.getInt("category");
mCurPosition = savedInstanceState.getInt("listPosition");
updateContentAndRecycleBitmap(mCategory, mCurPosition);
}
}

if (mSoloFragment) {
String title = Directory.getCategory(mCategory).getEntry(mCurPosition).getName();
ActionBar bar = getActivity().getActionBar();
bar.setTitle(title);
}
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// This callback is used only when mSoloFragment == true (see onActivityCreated above)
switch (item.getItemId()) {
case android.R.id.home:
// App icon in Action Bar clicked; go up
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Reuse the existing instance
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}

@Override
public void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("listPosition", mCurPosition);
outState.putInt("category", mCategory);
outState.putBoolean("systemUiVisible", mSystemUiVisible);
}

/** Toggle whether the system UI (status bar / system bar) is visible.
*  This also toggles the action bar visibility.
* @param show True to show the system UI, false to hide it.
*/
void setSystemUiVisible(boolean show) {
mSystemUiVisible = show;

Window window = getActivity().getWindow();
WindowManager.LayoutParams winParams = window.getAttributes();
View view = getView();
ActionBar actionBar = getActivity().getActionBar();

if (show) {
// Show status bar (remove fullscreen flag)
window.setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Show system bar
view.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
// Show action bar
actionBar.show();
} else {
// Add fullscreen flag (hide status bar)
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Hide system bar
view.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
// Hide action bar
actionBar.hide();
}
window.setAttributes(winParams);
}

boolean processDragStarted(DragEvent event) {
// Determine whether to continue processing drag and drop based on the
// plain text mime type.
ClipDescription clipDesc = event.getClipDescription();
if (clipDesc != null) {
return clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
}
return false;
}

boolean processDrop(DragEvent event, ImageView imageView) {
// Attempt to parse clip data with expected format: category||entry_id.
// Ignore event if data does not conform to this format.
ClipData data = event.getClipData();
if (data != null) {
if (data.getItemCount() > 0) {
Item item = data.getItemAt(0);
String textData = (String) item.getText();
if (textData != null) {
StringTokenizer tokenizer = new StringTokenizer(textData, "||");
if (tokenizer.countTokens() != 2) {
return false;
}
int category = -1;
int entryId = -1;
try {
category = Integer.parseInt(tokenizer.nextToken());
entryId = Integer.parseInt(tokenizer.nextToken());
} catch (NumberFormatException exception) {
return false;
}
updateContentAndRecycleBitmap(category, entryId);
// Update list fragment with selected entry.
TitlesFragment titlesFrag = (TitlesFragment)
getFragmentManager().findFragmentById(R.id.titles_frag);
titlesFrag.selectPosition(entryId);
return true;
}
}
}
return false;
}

/**
* Sets the current image visible.
* @param category Index position of the image category
* @param position Index position of the image
*/
void updateContentAndRecycleBitmap(int category, int position) {
mCategory = category;
mCurPosition = position;

if (mCurrentActionMode != null) {
mCurrentActionMode.finish();
}

if (mBitmap != null) {
// This is an advanced call and should be used if you
// are working with a lot of bitmaps. The bitmap is dead
// after this call.
mBitmap.recycle();
}

// Get the bitmap that needs to be drawn and update the ImageView
mBitmap = Directory.getCategory(category).getEntry(position)
.getBitmap(getResources());
((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);
}

/** Share the currently selected photo using an AsyncTask to compress the image
* and then invoke the appropriate share intent.
*/
void shareCurrentPhoto() {
File externalCacheDir = getActivity().getExternalCacheDir();
if (externalCacheDir == null) {
Toast.makeText(getActivity(), "Error writing to USB/external storage.",
Toast.LENGTH_SHORT).show();
return;
}

// Prevent media scanning of the cache directory.
final File noMediaFile = new File(externalCacheDir, ".nomedia");
try {
noMediaFile.createNewFile();
} catch (IOException e) {
}

// Write the bitmap to temporary storage in the external storage directory (e.g. SD card).
// We perform the actual disk write operations on a separate thread using the
// {@link AsyncTask} class, thus avoiding the possibility of stalling the main (UI) thread.

final File tempFile = new File(externalCacheDir, "tempfile.jpg");

new AsyncTask<Void, Void, Boolean>() {
/**
* Compress and write the bitmap to disk on a separate thread.
* @return TRUE if the write was successful, FALSE otherwise.
*/
@Override
protected Boolean doInBackground(Void... voids) {
try {
FileOutputStream fo = new FileOutputStream(tempFile, false);
if (!mBitmap.compress(Bitmap.CompressFormat.JPEG, 60, fo)) {
Toast.makeText(getActivity(), "Error writing bitmap data.",
Toast.LENGTH_SHORT).show();
return Boolean.FALSE;
}
return Boolean.TRUE;

} catch (FileNotFoundException e) {
Toast.makeText(getActivity(), "Error writing to USB/external storage.",
Toast.LENGTH_SHORT).show();
return Boolean.FALSE;
}
}

/**
* After doInBackground completes (either successfully or in failure), we invoke an
* intent to share the photo. This code is run on the main (UI) thread.
*/
@Override
protected void onPostExecute(Boolean result) {
if (result != Boolean.TRUE) {
return;
}

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, "Share photo"));
}
}.execute();
}

/**
* The callback for the 'photo selected' {@link ActionMode}. In this action mode, we can
* provide contextual actions for the selected photo. We currently only provide the 'share'
* action, but we could also add clipboard functions such as cut/copy/paste here as well.
*/
private ActionMode.Callback mContentSelectionActionModeCallback = new ActionMode.Callback() {
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
actionMode.setTitle(R.string.photo_selection_cab_title);

MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.photo_context_menu, menu);
return true;
}

public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}

public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_share:
shareCurrentPhoto();
actionMode.finish();
return true;
}
return false;
}

public void onDestroyActionMode(ActionMode actionMode) {
mContentView.setSelected(false);
mCurrentActionMode = null;
}
};
}

public class Directory {
private static DirectoryCategory[] mCategories;

public static void initializeDirectory() {
mCategories = new DirectoryCategory[] {
new DirectoryCategory("Balloons", new DirectoryEntry[] {
new DirectoryEntry("Red Balloon", R.drawable.red_balloon),
new DirectoryEntry("Green Balloon", R.drawable.green_balloon),
new DirectoryEntry("Blue Balloon", R.drawable.blue_balloon)}),
new DirectoryCategory("Bikes", new DirectoryEntry[] {
new DirectoryEntry("Old school huffy", R.drawable.blue_bike),
new DirectoryEntry("New Bikes", R.drawable.rainbow_bike),
new DirectoryEntry("Chrome Fast", R.drawable.chrome_wheel)}),
new DirectoryCategory("Androids", new DirectoryEntry[] {
new DirectoryEntry("Steampunk Android", R.drawable.punk_droid),
new DirectoryEntry("Stargazing Android", R.drawable.stargazer_droid),
new DirectoryEntry("Big Android", R.drawable.big_droid) }),
new DirectoryCategory("Pastries", new DirectoryEntry[] {
new DirectoryEntry("Cupcake", R.drawable.cupcake),
new DirectoryEntry("Donut", R.drawable.donut),
new DirectoryEntry("Eclair", R.drawable.eclair),
new DirectoryEntry("Froyo", R.drawable.froyo), }), };

}

public static int getCategoryCount() {
return mCategories.length;
}

public static DirectoryCategory getCategory(int i) {
return mCategories[i];
}
}

public class DirectoryCategory {
private String name;
private DirectoryEntry[] entries;

public DirectoryCategory(String name, DirectoryEntry[] entries) {
this.name = name;
this.entries = entries;
}

public String getName() {
return name;
}

public int getEntryCount() {
return entries.length;
}

public DirectoryEntry getEntry(int i) {
return entries[i];
}
}

public class DirectoryEntry {
private String name;
private int resID;

public DirectoryEntry(String name, int resID) {
this.name = name;
this.resID = resID;
}

public String getName() {
return name;
}

public Drawable getDrawable(Resources res) {
return res.getDrawable(resID);
}

public Bitmap getBitmap(Resources res) {
return BitmapFactory.decodeResource(res, resID);
}
}

public class FitCenterFrameLayout extends ViewGroup {
public FitCenterFrameLayout(Context context) {
super(context);
}

public FitCenterFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);

int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
int childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED);

int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
getChildAt(i).measure(childWidthSpec, childHeightSpec);
}
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int childCount = getChildCount();

final int parentLeft = getPaddingLeft();
final int parentTop = getPaddingTop();
final int parentRight = r - l - getPaddingRight();
final int parentBottom = b - t - getPaddingBottom();

final int parentWidth = parentRight - parentLeft;
final int parentHeight = parentBottom - parentTop;

int unpaddedWidth, unpaddedHeight, parentUnpaddedWidth, parentUnpaddedHeight;
int childPaddingLeft, childPaddingTop, childPaddingRight, childPaddingBottom;

for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}

// Fit and center the child within the parent. Make sure not to consider padding
// as part of the child's aspect ratio.

childPaddingLeft = child.getPaddingLeft();
childPaddingTop = child.getPaddingTop();
childPaddingRight = child.getPaddingRight();
childPaddingBottom = child.getPaddingBottom();

unpaddedWidth = child.getMeasuredWidth() - childPaddingLeft - childPaddingRight;
unpaddedHeight = child.getMeasuredHeight() - childPaddingTop - childPaddingBottom;

parentUnpaddedWidth = parentWidth - childPaddingLeft - childPaddingRight;
parentUnpaddedHeight = parentHeight - childPaddingTop - childPaddingBottom;

if (parentUnpaddedWidth * unpaddedHeight > parentUnpaddedHeight * unpaddedWidth) {
// The child view should be left/right letterboxed.
final int scaledChildWidth = unpaddedWidth * parentUnpaddedHeight
/ unpaddedHeight + childPaddingLeft + childPaddingRight;
child.layout(
parentLeft + (parentWidth - scaledChildWidth) / 2,
parentTop,
parentRight - (parentWidth - scaledChildWidth) / 2,
parentBottom);
} else {
// The child view should be top/bottom letterboxed.
final int scaledChildHeight = unpaddedHeight * parentUnpaddedWidth
/ unpaddedWidth + childPaddingTop + childPaddingBottom;
child.layout(
parentLeft,
parentTop + (parentHeight - scaledChildHeight) / 2,
parentRight,
parentTop + (parentHeight + scaledChildHeight) / 2);
}
}
}
}

/**
* Fragment that shows the list of images
* As an extension of ListFragment, this fragment uses a default layout
* that includes a single ListView, which you can acquire with getListView()
* When running on a screen size smaller than "large", this fragment appears alone
* in MainActivity. In this case, selecting a list item opens the ContentActivity,
* which likewise holds only the ContentFragment.
*/
public class TitlesFragment extends ListFragment implements ActionBar.TabListener {
OnItemSelectedListener mListener;
private int mCategory = 0;
private int mCurPosition = 0;
private boolean mDualFragments = false;

/** Container Activity must implement this interface and we ensure
* that it does during the onAttach() callback
*/
public interface OnItemSelectedListener {
public void onItemSelected(int category, int position);
}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Check that the container activity has implemented the callback interface
try {
mListener = (OnItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnItemSelectedListener");
}
}

/** This is where we perform setup for the fragment that's either
* not related to the fragment's layout or must be done after the layout is drawn.
* Notice that this fragment does not implement onCreateView(), because it extends
* ListFragment, which includes a ListView as the root view by default, so there's
* no need to set up the layout.
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

ContentFragment frag = (ContentFragment) getFragmentManager()
.findFragmentById(R.id.content_frag);
if (frag != null) mDualFragments = true;

ActionBar bar = getActivity().getActionBar();
bar.setDisplayHomeAsUpEnabled(false);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

// Must call in order to get callback to onCreateOptionsMenu()
setHasOptionsMenu(true);

Directory.initializeDirectory();
for (int i = 0; i < Directory.getCategoryCount(); i++) {
bar.addTab(bar.newTab().setText(Directory.getCategory(i).getName())
.setTabListener(this));
}

//Current position should survive screen rotations.
if (savedInstanceState != null) {
mCategory = savedInstanceState.getInt("category");
mCurPosition = savedInstanceState.getInt("listPosition");
bar.selectTab(bar.getTabAt(mCategory));
}

populateTitles(mCategory);
ListView lv = getListView();
lv.setCacheColorHint(Color.TRANSPARENT); // Improves scrolling performance

if (mDualFragments) {
// Highlight the currently selected item
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Enable drag and dropping
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
final String title = (String) ((TextView) v).getText();

// Set up clip data with the category||entry_id format.
final String textData = String.format("%d||%d", mCategory, pos);
ClipData data = ClipData.newPlainText(title, textData);
v.startDrag(data, new MyDragShadowBuilder(v), null, 0);
return true;
}
});
}

// If showing both fragments, select the appropriate list item by default
if (mDualFragments) selectPosition(mCurPosition);

// Attach a GlobalLayoutListener so that we get a callback when the layout
// has finished drawing. This is necessary so that we can apply top-margin
// to the ListView in order to dodge the ActionBar. Ordinarily, that's not
// necessary, but we've set the ActionBar to "overlay" mode using our theme,
// so the layout does not account for the action bar position on its own.
ViewTreeObserver observer = getListView().getViewTreeObserver();
observer.addOnGlobalLayoutListener(layoutListener);
}

@Override
public void onDestroyView() {
super.onDestroyView();
// Always detach ViewTreeObserver listeners when the view tears down
getListView().getViewTreeObserver().removeGlobalOnLayoutListener(layoutListener);
}

/** Attaches an adapter to the fragment's ListView to populate it with items */
public void populateTitles(int category) {
DirectoryCategory cat = Directory.getCategory(category);
String[] items = new String[cat.getEntryCount()];
for (int i = 0; i < cat.getEntryCount(); i++)
items[i] = cat.getEntry(i).getName();
// Convenience method to attach an adapter to ListFragment's ListView
setListAdapter(new ArrayAdapter<String>(getActivity(),
R.layout.title_list_item, items));
mCategory = category;
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Send the event to the host activity via OnItemSelectedListener callback
mListener.onItemSelected(mCategory, position);
mCurPosition = position;
}

/** Called to select an item from the listview */
public void selectPosition(int position) {
// Only if we're showing both fragments should the item be "highlighted"
if (mDualFragments) {
ListView lv = getListView();
lv.setItemChecked(position, true);
}
// Calls the parent activity's implementation of the OnItemSelectedListener
// so the activity can pass the event to the sibling fragment as appropriate
mListener.onItemSelected(mCategory, position);
}

@Override
public void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("listPosition", mCurPosition);
outState.putInt("category", mCategory);
}

/** This defines how the draggable list items appear during a drag event */
private class MyDragShadowBuilder extends View.DragShadowBuilder {
private Drawable mShadow;

public MyDragShadowBuilder(View v) {
super(v);

final TypedArray a = v.getContext().obtainStyledAttributes(R.styleable.AppTheme);
mShadow = a.getDrawable(R.styleable.AppTheme_listDragShadowBackground);
mShadow.setCallback(v);
mShadow.setBounds(0, 0, v.getWidth(), v.getHeight());
a.recycle();
}

@Override
public void onDrawShadow(Canvas canvas) {
super.onDrawShadow(canvas);
mShadow.draw(canvas);
getView().draw(canvas);
}
}

// Because the fragment doesn't have a reliable callback to notify us when
// the activity's layout is completely drawn, this OnGlobalLayoutListener provides
// the necessary callback so we can add top-margin to the ListView in order to dodge
// the ActionBar. Which is necessary because the ActionBar is in overlay mode, meaning
// that it will ordinarily sit on top of the activity layout as a top layer and
// the ActionBar height can vary. Specifically, when on a small/normal size screen,
// the action bar tabs appear in a second row, making the action bar twice as tall.
ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int barHeight = getActivity().getActionBar().getHeight();
ListView listView = getListView();
FrameLayout.LayoutParams params = (LayoutParams) listView.getLayoutParams();
// The list view top-margin should always match the action bar height
if (params.topMargin != barHeight) {
params.topMargin = barHeight;
listView.setLayoutParams(params);
}
// The action bar doesn't update its height when hidden, so make top-margin zero
if (!getActivity().getActionBar().isShowing()) {
params.topMargin = 0;
listView.setLayoutParams(params);
}
}
};

/* The following are callbacks implemented for the ActionBar.TabListener,
* which this fragment implements to handle events when tabs are selected.
*/

public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
TitlesFragment titleFrag = (TitlesFragment) getFragmentManager()
.findFragmentById(R.id.titles_frag);
titleFrag.populateTitles(tab.getPosition());

if (mDualFragments) {
titleFrag.selectPosition(0);
}
}

/* These must be implemented, but we don't use them */

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}

public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: