Java tutorial
/* * Copyright (C) 2009 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 org.mariotaku.gallery3d; import android.app.ActionBar; import android.app.ActionBar.OnMenuVisibilityListener; import android.content.ActivityNotFoundException; import android.content.Intent; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; import android.view.SubMenu; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.ProgressBar; import me.imid.swipebacklayout.lib.SwipeBackLayout.SwipeListener; import org.mariotaku.gallery3d.ui.GLRoot; import org.mariotaku.gallery3d.ui.GLRootView; import org.mariotaku.gallery3d.ui.GLView; import org.mariotaku.gallery3d.ui.PhotoView; import org.mariotaku.gallery3d.ui.SynchronizedHandler; import org.mariotaku.gallery3d.util.GalleryUtils; import org.mariotaku.gallery3d.util.ThreadPool; import org.mariotaku.menucomponent.widget.MenuBar; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.support.TwidereSwipeBackActivity; import org.mariotaku.twidere.util.SaveImageTask; import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.Utils; import java.io.File; public final class ImageViewerGLActivity extends TwidereSwipeBackActivity implements Constants, PhotoView.Listener, GLImageLoader.DownloadListener, LoaderManager.LoaderCallbacks<GLImageLoader.Result>, OnMenuVisibilityListener, SwipeListener, OnMenuItemClickListener { private final GLView mRootPane = new GLView() { @Override protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { mPhotoView.layout(0, 0, right - left, bottom - top); } }; protected static final int FLAG_HIDE_ACTION_BAR = 1; protected static final int FLAG_HIDE_STATUS_BAR = 2; private static final int MSG_HIDE_BARS = 1; private static final int MSG_ON_FULL_SCREEN_CHANGED = 4; private static final int MSG_UPDATE_ACTION_BAR = 5; private static final int MSG_UNFREEZE_GLROOT = 6; private static final int MSG_WANT_BARS = 7; private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8; private static final int UNFREEZE_GLROOT_TIMEOUT = 250; private ActionBar mActionBar; private GLView mContentPane; private GLRootView mGLRootView; private ProgressBar mProgress; private ImageView mImageViewer; private MenuBar mMenuBar; private PhotoView mPhotoView; private PhotoView.ITileImageAdapter mAdapter; private Handler mHandler; protected int mFlags; private boolean mShowBars = true; private boolean mActionBarAllowed = true; private boolean mLoaderInitialized; private long mContentLength; private ThreadPool mThreadPool; private File mImageFile; public GLRoot getGLRoot() { return mGLRootView; } @Override public int getThemeResourceId() { return ThemeUtils.getViewerThemeResource(this); } public ThreadPool getThreadPool() { if (mThreadPool != null) return mThreadPool; return mThreadPool = new ThreadPool(); } public void hideProgress() { mProgress.setVisibility(View.GONE); mProgress.setProgress(0); } @Override public void onActionBarAllowed(final boolean allowed) { mActionBarAllowed = allowed; mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR); } @Override public void onActionBarWanted() { mHandler.sendEmptyMessage(MSG_WANT_BARS); } @Override public void onContentChanged() { super.onContentChanged(); mGLRootView = (GLRootView) findViewById(R.id.gl_root_view); mImageViewer = (ImageView) findViewById(R.id.image_viewer); mProgress = (ProgressBar) findViewById(R.id.progress); mMenuBar = (MenuBar) findViewById(R.id.menu_bar); } @Override public Loader<GLImageLoader.Result> onCreateLoader(final int id, final Bundle args) { mProgress.setVisibility(View.VISIBLE); mProgress.setIndeterminate(true); invalidateOptionsMenu(); final Uri uri = args != null ? (Uri) args.getParcelable(EXTRA_URI) : null; return new GLImageLoader(this, this, uri); } @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.menu_image_viewer_action_bar, menu); return true; } @Override public void onCurrentImageUpdated() { mGLRootView.unfreeze(); } @Override public void onDownloadError(final Throwable t) { mContentLength = 0; } @Override public void onDownloadFinished() { mContentLength = 0; } @Override public void onDownloadStart(final long total) { mContentLength = total; mProgress.setIndeterminate(total <= 0); mProgress.setMax(total > 0 ? (int) (total / 1024) : 0); } @Override public void onEdgeTouch(final int edgeFlag) { showBars(); } @Override public void onLoaderReset(final Loader<GLImageLoader.Result> loader) { } @Override public void onLoadFinished(final Loader<GLImageLoader.Result> loader, final GLImageLoader.Result data) { if (data != null && (data.decoder != null || data.bitmap != null)) { if (data.decoder != null) { mGLRootView.setVisibility(View.VISIBLE); mImageViewer.setVisibility(View.GONE); mAdapter.setData(data.decoder, data.bitmap, data.orientation); mImageViewer.setImageBitmap(null); } else if (data.bitmap != null) { mGLRootView.setVisibility(View.GONE); mImageViewer.setVisibility(View.VISIBLE); mImageViewer.setImageBitmap(data.bitmap); } mImageFile = data.file; } else { mImageFile = null; if (data != null) { Utils.showErrorMessage(this, null, data.exception, true); } } mProgress.setVisibility(View.GONE); mProgress.setProgress(0); invalidateOptionsMenu(); updateShareIntent(); } @Override public boolean onMenuItemClick(final MenuItem item) { switch (item.getItemId()) { case MENU_SAVE: { if (mImageFile != null) { new SaveImageTask(this, mImageFile).execute(); } break; } case MENU_OPEN_IN_BROWSER: { final Intent intent = getIntent(); intent.setExtrasClassLoader(getClassLoader()); final Uri uri = intent.getData(); final Uri orig = intent.getParcelableExtra(EXTRA_URI_ORIG); final Uri uriPreferred = orig != null ? orig : uri; if (uriPreferred == null) return false; final String scheme = uriPreferred.getScheme(); if ("http".equals(scheme) || "https".equals(scheme)) { final Intent open_intent = new Intent(Intent.ACTION_VIEW, uriPreferred); open_intent.addCategory(Intent.CATEGORY_BROWSABLE); try { startActivity(open_intent); } catch (final ActivityNotFoundException e) { // Ignore. } } break; } default: { final Intent intent = item.getIntent(); if (intent != null) { try { startActivity(intent); } catch (final ActivityNotFoundException e) { // Ignore. } return true; } return false; } } return true; } @Override public void onMenuVisibilityChanged(final boolean isVisible) { } @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case MENU_HOME: { onBackPressed(); break; } case MENU_REFRESH: { loadImage(); break; } } return true; } @Override public void onPictureCenter() { mPhotoView.setWantPictureCenterCallbacks(false); } @Override public boolean onPrepareOptionsMenu(final Menu menu) { final LoaderManager lm = getSupportLoaderManager(); Utils.setMenuItemAvailability(menu, MENU_REFRESH, !lm.hasRunningLoaders()); return super.onPrepareOptionsMenu(menu); } @Override public void onProgressUpdate(final long downloaded) { if (mContentLength == 0) { mProgress.setIndeterminate(true); return; } mProgress.setIndeterminate(false); mProgress.setProgress((int) (downloaded / 1024)); } @Override public void onScrollOverThreshold() { } @Override public void onScrollStateChange(final int state, final float scrollPercent) { } @Override public void onSingleTapUp(final int x, final int y) { toggleBars(); } public void showProgress() { mProgress.setVisibility(View.VISIBLE); mProgress.setIndeterminate(true); } @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.image_viewer_gl); mActionBar = getActionBar(); mActionBar.setDisplayHomeAsUpEnabled(true); mActionBar.addOnMenuVisibilityListener(this); mHandler = new MyHandler(this); mPhotoView = new PhotoView(this); mPhotoView.setListener(this); final int bgColor = ThemeUtils.getColorBackgroundCacheHint(this); final int r = Color.red(bgColor), g = Color.green(bgColor), b = Color.blue(bgColor); final float[] rootBg = { r / 255f, g / 255f, b / 255f, 1 }; mRootPane.setBackgroundColor(rootBg); mRootPane.addComponent(mPhotoView); mAdapter = new PhotoViewAdapter(mPhotoView); mPhotoView.setModel(mAdapter); if (savedInstanceState == null) { loadImage(); } mMenuBar.setOnMenuItemClickListener(this); mMenuBar.inflate(R.menu.menu_image_viewer); mMenuBar.setIsBottomBar(true); mMenuBar.show(); setSwipeListener(this); } @Override protected void onDestroy() { mActionBar.removeOnMenuVisibilityListener(this); super.onDestroy(); mGLRootView.lockRenderThread(); try { // Remove all pending messages. mHandler.removeCallbacksAndMessages(null); } finally { mGLRootView.unlockRenderThread(); } } @Override protected void onNewIntent(final Intent intent) { setIntent(intent); loadImage(); } @Override protected void onPause() { super.onPause(); mGLRootView.onPause(); mGLRootView.lockRenderThread(); try { mGLRootView.unfreeze(); mHandler.removeMessages(MSG_UNFREEZE_GLROOT); if (mAdapter != null) { mAdapter.recycleScreenNail(); } mPhotoView.pause(); mHandler.removeMessages(MSG_HIDE_BARS); mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS); } finally { mGLRootView.unlockRenderThread(); } } @Override protected void onResume() { super.onResume(); mGLRootView.lockRenderThread(); try { if (mAdapter == null) { finish(); return; } mGLRootView.freeze(); setContentPane(mRootPane); mPhotoView.resume(); if (!mShowBars) { hideBars(); } mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT); } finally { mGLRootView.unlockRenderThread(); } mGLRootView.onResume(); } @Override protected void onSaveInstanceState(final Bundle outState) { mGLRootView.lockRenderThread(); try { super.onSaveInstanceState(outState); } finally { mGLRootView.unlockRenderThread(); } } protected void setContentPane(final GLView content) { mContentPane = content; mContentPane.setBackgroundColor(GalleryUtils.intColorToFloatARGBArray(Color.BLACK)); mGLRootView.setContentPane(mContentPane); } private boolean canShowBars() { // No bars if it's not allowed. if (!mActionBarAllowed) return false; return true; } private void hideBars() { if (!mShowBars || isSwiping()) return; mShowBars = false; mActionBar.hide(); final TranslateAnimation anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1); anim.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime)); anim.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(final Animation animation) { mMenuBar.setVisibility(View.GONE); } @Override public void onAnimationRepeat(final Animation animation) { } @Override public void onAnimationStart(final Animation animation) { } }); mMenuBar.startAnimation(anim); mHandler.removeMessages(MSG_HIDE_BARS); } private void loadImage() { getSupportLoaderManager().destroyLoader(0); final Uri uri = getIntent().getData(); if (uri == null) { finish(); return; } final Bundle args = new Bundle(); args.putParcelable(EXTRA_URI, uri); if (!mLoaderInitialized) { getSupportLoaderManager().initLoader(0, args, this); mLoaderInitialized = true; } else { getSupportLoaderManager().restartLoader(0, args, this); } } private void showBars() { if (mShowBars) return; mShowBars = true; mActionBar.show(); mMenuBar.setVisibility(View.VISIBLE); final TranslateAnimation anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0); anim.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime)); mMenuBar.startAnimation(anim); } private void toggleBars() { if (mShowBars) { hideBars(); } else { if (canShowBars()) { showBars(); } } } private void updateBars() { if (!canShowBars()) { hideBars(); } } private void wantBars() { if (canShowBars()) { showBars(); } } void updateShareIntent() { final MenuItem item = mMenuBar.getMenu().findItem(MENU_SHARE); if (item == null || !item.hasSubMenu()) return; final SubMenu subMenu = item.getSubMenu(); subMenu.clear(); final Intent intent = getIntent(); final Uri uri = intent.getData(); final Intent shareIntent = new Intent(Intent.ACTION_SEND); if (mImageFile != null && mImageFile.exists()) { shareIntent.setType("image/*"); shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(mImageFile)); } else { shareIntent.setType("text/plain"); shareIntent.putExtra(Intent.EXTRA_TEXT, uri.toString()); } Utils.addIntentToMenu(this, subMenu, shareIntent); } private static class MyHandler extends SynchronizedHandler { ImageViewerGLActivity activity; private MyHandler(final ImageViewerGLActivity activity) { super(activity.getGLRoot()); this.activity = activity; } @Override public void handleMessage(final Message message) { switch (message.what) { case MSG_HIDE_BARS: { activity.hideBars(); break; } case MSG_REFRESH_BOTTOM_CONTROLS: { break; } case MSG_ON_FULL_SCREEN_CHANGED: { break; } case MSG_UPDATE_ACTION_BAR: { activity.updateBars(); break; } case MSG_WANT_BARS: { activity.wantBars(); break; } case MSG_UNFREEZE_GLROOT: { mGLRoot.unfreeze(); break; } } } } }