Merge pull request #607 from nextcloud/integration-with-master

PNG files have full-screen checkerboard background & Better emptycontent view for file types which can not be shown
This commit is contained in:
Tobias Kaminsky 2017-04-05 08:35:56 +02:00 committed by GitHub
commit 8ff753f623
12 changed files with 411 additions and 296 deletions

View file

@ -39,12 +39,12 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import java.util.Formatter;
import java.util.Locale;
import com.owncloud.android.R;
import com.owncloud.android.utils.DisplayUtils;
import java.util.Formatter;
import java.util.Locale;
/**
* View containing controls for a {@link MediaPlayer}.

View file

@ -26,17 +26,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import com.ortiz.touch.ExtendedViewPager;
import com.owncloud.android.MainApp;
@ -69,15 +65,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
public class PreviewImageActivity extends FileActivity implements
FileFragment.ContainerActivity,
ViewPager.OnPageChangeListener, OnRemoteOperationListener {
public static final int DIALOG_SHORT_WAIT = 0;
public static final String TAG = PreviewImageActivity.class.getSimpleName();
public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
private static final String KEY_WAITING_FOR_BINDER = "WAITING_FOR_BINDER";
private static final int INITIAL_HIDE_DELAY = 0; // immediate hide
private static final String KEY_SYSTEM_VISIBLE = "TRUE";
private ExtendedViewPager mViewPager;
private PreviewImagePagerAdapter mPreviewImagePagerAdapter;
@ -92,20 +85,22 @@ public class PreviewImageActivity extends FileActivity implements
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar();
if (savedInstanceState != null && !savedInstanceState.getBoolean(KEY_SYSTEM_VISIBLE, true) &&
actionBar != null) {
actionBar.hide();
}
setContentView(R.layout.preview_image_activity);
// Navigation Drawer
setupDrawer();
// ActionBar
ActionBar actionBar = getSupportActionBar();
updateActionBarTitleAndHomeButton(null);
actionBar.hide();
mFullScreenAnchorView = getWindow().getDecorView();
// to keep our UI controls visibility in line with system bars visibility
@ -115,7 +110,6 @@ public class PreviewImageActivity extends FileActivity implements
@Override
public void onSystemUiVisibilityChange(int flags) {
boolean visible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
ActionBar actionBar = getSupportActionBar();
if (visible) {
actionBar.show();
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
@ -125,11 +119,7 @@ public class PreviewImageActivity extends FileActivity implements
}
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(getResources().getColor(R.color.owncloud_blue_dark_transparent));
}
if (savedInstanceState != null) {
mRequestWaitingForBinder = savedInstanceState.getBoolean(KEY_WAITING_FOR_BINDER);
} else {
@ -164,43 +154,7 @@ public class PreviewImageActivity extends FileActivity implements
mRequestWaitingForBinder = true;
}
}
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available
delayedHide(INITIAL_HIDE_DELAY);
}
Handler mHideSystemUiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
hideSystemUI(mFullScreenAnchorView);
getSupportActionBar().hide();
}
};
private void delayedHide(int delayMillis) {
mHideSystemUiHandler.removeMessages(0);
mHideSystemUiHandler.sendEmptyMessageDelayed(0, delayMillis);
}
/// handle Window Focus changes
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// When the window loses focus (e.g. the action overflow is shown),
// cancel any pending hide action.
if (!hasFocus) {
mHideSystemUiHandler.removeMessages(0);
}
}
@Override
public void onStart() {
super.onStart();
@ -209,7 +163,8 @@ public class PreviewImageActivity extends FileActivity implements
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_WAITING_FOR_BINDER, mRequestWaitingForBinder);
outState.putBoolean(KEY_WAITING_FOR_BINDER, mRequestWaitingForBinder);
outState.putBoolean(KEY_SYSTEM_VISIBLE, getSystemUIVisible());
}
@Override
@ -463,6 +418,13 @@ public class PreviewImageActivity extends FileActivity implements
}
public boolean getSystemUIVisible() {
if (getSupportActionBar() != null) {
return (getSupportActionBar().isShowing());
}
return true;
}
@SuppressLint("InlinedApi")
public void toggleFullScreen() {
@ -543,7 +505,7 @@ public class PreviewImageActivity extends FileActivity implements
anchorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE // draw full window; Android >= 4.1
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // draw full window; Android >= 4.1
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // draw full window; Android >= 4.1
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // draw full window; Android >= 4.
);
}
}

View file

@ -1,33 +1,40 @@
/**
* ownCloud Android client application
*
* @author David A. Velasco
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ownCloud Android client application
*
* @author David A. Velasco
* Copyright (C) 2015 ownCloud Inc.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.preview;
import android.accounts.Account;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -36,7 +43,9 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.owncloud.android.R;
@ -61,7 +70,7 @@ import third_parties.michaelOrtiz.TouchImageViewCustom;
*
* Trying to get an instance with a NULL {@link OCFile} will produce an
* {@link IllegalStateException}.
*
*
* If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on
* instantiation too.
*/
@ -75,8 +84,13 @@ public class PreviewImageFragment extends FileFragment {
private static final String SCREEN_NAME = "Image Preview";
private TouchImageViewCustom mImageView;
private TextView mMessageView;
private ProgressBar mProgressWheel;
private RelativeLayout mMultiView;
protected LinearLayout mMultiListContainer;
protected TextView mMultiListMessage;
protected TextView mMultiListHeadline;
protected ImageView mMultiListIcon;
protected ProgressBar mMultiListProgress;
public Bitmap mBitmap = null;
@ -86,7 +100,6 @@ public class PreviewImageFragment extends FileFragment {
private LoadBitmapTask mLoadBitmapTask = null;
/**
* Public factory method to create a new fragment that previews an image.
*
@ -101,7 +114,7 @@ public class PreviewImageFragment extends FileFragment {
* {@link FragmentStatePagerAdapter}
* ; TODO better solution
*/
public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState){
public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState) {
PreviewImageFragment frag = new PreviewImageFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_FILE, imageFile);
@ -111,13 +124,12 @@ public class PreviewImageFragment extends FileFragment {
}
/**
* Creates an empty fragment for image previews.
*
*
* MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
* (for instance, when the device is turned a aside).
*
*
* DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
* construction
*/
@ -133,9 +145,9 @@ public class PreviewImageFragment extends FileFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
setFile((OCFile)args.getParcelable(ARG_FILE));
// TODO better in super, but needs to check ALL the class extending FileFragment;
// not right now
setFile((OCFile) args.getParcelable(ARG_FILE));
// TODO better in super, but needs to check ALL the class extending FileFragment;
// not right now
mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST);
setHasOptionsMenu(true);
@ -152,20 +164,39 @@ public class PreviewImageFragment extends FileFragment {
View view = inflater.inflate(R.layout.preview_image_fragment, container, false);
mImageView = (TouchImageViewCustom) view.findViewById(R.id.image);
mImageView.setVisibility(View.GONE);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((PreviewImageActivity) getActivity()).toggleFullScreen();
toggleImageBackground();
}
});
mImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((PreviewImageActivity) getActivity()).toggleFullScreen();
toggleImageBackground();
}
});
mMessageView = (TextView)view.findViewById(R.id.message);
mMessageView.setVisibility(View.GONE);
mProgressWheel = (ProgressBar)view.findViewById(R.id.progressWheel);
mProgressWheel.setVisibility(View.VISIBLE);
mMultiView = (RelativeLayout) view.findViewById(R.id.multi_view);
setupMultiView(view);
setMultiListLoadingMessage();
return view;
}
protected void setupMultiView(View view) {
mMultiListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
mMultiListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
mMultiListHeadline = (TextView) view.findViewById(R.id.empty_list_view_headline);
mMultiListIcon = (ImageView) view.findViewById(R.id.empty_list_icon);
mMultiListProgress = (ProgressBar) view.findViewById(R.id.empty_list_progress);
}
/**
* {@inheritDoc}
*/
@ -203,7 +234,7 @@ public class PreviewImageFragment extends FileFragment {
public void onStart() {
super.onStart();
if (getFile() != null) {
mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel);
mLoadBitmapTask = new LoadBitmapTask(mImageView);
//mLoadBitmapTask.execute(new String[]{getFile().getStoragePath()});
// mLoadBitmapTask.execute(getFile().getStoragePath());
mLoadBitmapTask.execute(getFile());
@ -242,10 +273,10 @@ public class PreviewImageFragment extends FileFragment {
setFile(mContainerActivity.getStorageManager().getFileById(getFile().getFileId()));
FileMenuFilter mf = new FileMenuFilter(
getFile(),
mContainerActivity.getStorageManager().getAccount(),
mContainerActivity,
getActivity()
getFile(),
mContainerActivity.getStorageManager().getAccount(),
mContainerActivity,
getActivity()
);
mf.filter(menu);
}
@ -303,31 +334,31 @@ public class PreviewImageFragment extends FileFragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_share_file: {
case R.id.action_share_file:
mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
return true;
}
case R.id.action_open_file_with: {
case R.id.action_open_file_with:
openFile();
return true;
}
case R.id.action_remove_file: {
case R.id.action_remove_file:
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}
case R.id.action_see_details: {
case R.id.action_see_details:
seeDetails();
return true;
}
case R.id.action_send_file: {
case R.id.action_send_file:
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
return true;
}
case R.id.action_sync_file: {
case R.id.action_sync_file:
mContainerActivity.getFileOperationsHelper().syncFile(getFile());
return true;
}
default:
return super.onOptionsItemSelected(item);
}
@ -349,9 +380,9 @@ public class PreviewImageFragment extends FileFragment {
if (mBitmap != null) {
mBitmap.recycle();
System.gc();
// putting this in onStop() is just the same; the fragment is always destroyed by
// {@link FragmentStatePagerAdapter} when the fragment in swiped further than the
// valid offscreen distance, and onStop() is never called before than that
// putting this in onStop() is just the same; the fragment is always destroyed by
// {@link FragmentStatePagerAdapter} when the fragment in swiped further than the
// valid offscreen distance, and onStop() is never called before than that
}
super.onDestroy();
}
@ -365,7 +396,7 @@ public class PreviewImageFragment extends FileFragment {
finish();
}
private class LoadBitmapTask extends AsyncTask<OCFile, Void, LoadImage> {
/**
@ -376,24 +407,6 @@ public class PreviewImageFragment extends FileFragment {
*/
private final WeakReference<ImageViewCustom> mImageViewRef;
/**
* Weak reference to the target {@link TextView} where error messages will be written.
*
* Using a weak reference will avoid memory leaks if the target ImageView is retired from
* memory before the load finishes.
*/
private final WeakReference<TextView> mMessageViewRef;
/**
* Weak reference to the target {@link ProgressBar} shown while the load is in progress.
*
* Using a weak reference will avoid memory leaks if the target ImageView is retired from
* memory before the load finishes.
*/
private final WeakReference<ProgressBar> mProgressWheelRef;
/**
* Error message to show when a load fails
*/
@ -405,11 +418,8 @@ public class PreviewImageFragment extends FileFragment {
*
* @param imageView Target {@link ImageView} where the bitmap will be loaded into.
*/
public LoadBitmapTask(ImageViewCustom imageView, TextView messageView,
ProgressBar progressWheel) {
public LoadBitmapTask(ImageViewCustom imageView) {
mImageViewRef = new WeakReference<ImageViewCustom>(imageView);
mMessageViewRef = new WeakReference<TextView>(messageView);
mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
}
@Override
@ -443,8 +453,10 @@ public class PreviewImageFragment extends FileFragment {
Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
break;
} else {
// Rotate image, obeying exif tag.
result = BitmapUtils.rotateImage(result, storagePath);
if (ocFile.getMimetype().equalsIgnoreCase("image/jpeg")) {
// Rotate image, obeying exif tag.
result = BitmapUtils.rotateImage(result, storagePath);
}
}
} catch (OutOfMemoryError e) {
@ -489,14 +501,12 @@ public class PreviewImageFragment extends FileFragment {
@Override
protected void onPostExecute(LoadImage result) {
hideProgressWheel();
if (result.bitmap != null) {
showLoadedImage(result);
}
else {
} else {
showErrorMessage();
}
if (result.bitmap != null && mBitmap != result.bitmap) {
if (result.bitmap != null && mBitmap != result.bitmap) {
// unused bitmap, release it! (just in case)
result.bitmap.recycle();
}
@ -510,54 +520,75 @@ public class PreviewImageFragment extends FileFragment {
Log_OC.d(TAG, "Showing image with resolution " + bitmap.getWidth() + "x" +
bitmap.getHeight());
if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")) {
Drawable backrepeat = getResources().getDrawable(R.drawable.backrepeat);
imageView.setBackground(backrepeat);
if (getResources() != null) {
Resources r = getResources();
Drawable[] layers = new Drawable[2];
layers[0] = r.getDrawable(R.color.white);
Drawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
layers[1] = bitmapDrawable;
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerHeight(0, convertDpToPixel(bitmap.getHeight(), getActivity()));
layerDrawable.setLayerHeight(1, convertDpToPixel(bitmap.getHeight(), getActivity()));
layerDrawable.setLayerWidth(0, convertDpToPixel(bitmap.getWidth(), getActivity()));
layerDrawable.setLayerWidth(1, convertDpToPixel(bitmap.getWidth(), getActivity()));
imageView.setImageDrawable(layerDrawable);
} else {
imageView.setImageBitmap(bitmap);
}
}
if (result.ocFile.getMimetype().equalsIgnoreCase("image/gif")) {
imageView.setGIFImageFromStoragePath(result.ocFile.getStoragePath());
} else {
} else if (!result.ocFile.getMimetype().equalsIgnoreCase("image/png")) {
imageView.setImageBitmap(bitmap);
}
imageView.setVisibility(View.VISIBLE);
mBitmap = bitmap; // needs to be kept for recycling when not useful
mBitmap = bitmap; // needs to be kept for recycling when not useful
}
final TextView messageView = mMessageViewRef.get();
if (messageView != null) {
messageView.setVisibility(View.GONE);
} // else , silently finish, the fragment was destroyed
mMultiView.setVisibility(View.GONE);
if (getResources() != null) {
mImageView.setBackgroundColor(getResources().getColor(R.color.black));
}
mImageView.setVisibility(View.VISIBLE);
}
private void showErrorMessage() {
final ImageView imageView = mImageViewRef.get();
if (imageView != null) {
// shows the default error icon
imageView.setVisibility(View.VISIBLE);
} // else , silently finish, the fragment was destroyed
final TextView messageView = mMessageViewRef.get();
if (messageView != null) {
messageView.setText(mErrorMessageId);
messageView.setVisibility(View.VISIBLE);
} // else , silently finish, the fragment was destroyed
mImageView.setBackgroundColor(Color.TRANSPARENT);
setMessageForMultiList(mErrorMessageId, R.string.preview_sorry, R.drawable.file_image);
}
}
private void hideProgressWheel() {
final ProgressBar progressWheel = mProgressWheelRef.get();
if (progressWheel != null) {
progressWheel.setVisibility(View.GONE);
}
private void setMultiListLoadingMessage() {
if (mMultiView != null) {
mMultiListHeadline.setText(R.string.file_list_loading);
mMultiListMessage.setText("");
mMultiListIcon.setVisibility(View.GONE);
mMultiListProgress.setVisibility(View.VISIBLE);
}
}
public void setMessageForMultiList(@StringRes int headline, @StringRes int message, @DrawableRes int icon) {
if (mMultiListContainer != null && mMultiListMessage != null) {
mMultiListHeadline.setText(headline);
mMultiListMessage.setText(message);
mMultiListIcon.setImageResource(icon);
mMultiListIcon.setVisibility(View.VISIBLE);
mMultiListProgress.setVisibility(View.GONE);
}
}
/**
* Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment}
* to be previewed.
*
*
* @param file File to test if can be previewed.
* @return 'True' if the file can be handled by the fragment.
*/
@ -574,6 +605,35 @@ public class PreviewImageFragment extends FileFragment {
container.finish();
}
private void toggleImageBackground() {
if (getFile() != null && getFile().getMimetype().equalsIgnoreCase("image/png") && getActivity() != null
&& getActivity() instanceof PreviewImageActivity && getResources() != null) {
PreviewImageActivity previewImageActivity = (PreviewImageActivity) getActivity();
LayerDrawable layerDrawable = (LayerDrawable) mImageView.getDrawable();
Drawable layerOne;
if (previewImageActivity.getSystemUIVisible()) {
layerOne = getResources().getDrawable(R.color.white);
} else {
layerOne = getResources().getDrawable(R.drawable.backrepeat);
}
layerDrawable.setDrawableByLayerId(layerDrawable.getId(0), layerOne);
mImageView.setImageDrawable(layerDrawable);
mImageView.invalidate();
}
}
private static int convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
int px = (int) (dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
public TouchImageViewCustom getImageView() {
return mImageView;
}
@ -582,7 +642,7 @@ public class PreviewImageFragment extends FileFragment {
private Bitmap bitmap;
private OCFile ocFile;
public LoadImage(Bitmap bitmap, OCFile ocFile){
public LoadImage(Bitmap bitmap, OCFile ocFile) {
this.bitmap = bitmap;
this.ocFile = ocFile;
}

View file

@ -23,7 +23,6 @@ import android.accounts.Account;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
@ -37,7 +36,8 @@ import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AlertDialog;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -47,6 +47,10 @@ import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
@ -69,7 +73,7 @@ import com.owncloud.android.utils.MimeTypeUtil;
*
* Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will
* produce an {@link IllegalStateException}.
*
*
* By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is
* generated on instantiation too.
*/
@ -87,6 +91,15 @@ public class PreviewMediaFragment extends FileFragment implements
private VideoView mVideoPreview;
private int mSavedPlaybackPosition;
private RelativeLayout mMultiView;
private RelativeLayout mPreviewContainer;
protected LinearLayout mMultiListContainer;
protected TextView mMultiListMessage;
protected TextView mMultiListHeadline;
protected ImageView mMultiListIcon;
protected ProgressBar mMultiListProgress;
private MediaServiceBinder mMediaServiceBinder = null;
private MediaControlView mMediaController = null;
private MediaServiceConnection mMediaServiceConnection = null;
@ -157,16 +170,50 @@ public class PreviewMediaFragment extends FileFragment implements
mView = inflater.inflate(R.layout.file_preview, container, false);
mPreviewContainer = (RelativeLayout) mView.findViewById(R.id.file_preview_container);
mImagePreview = (ImageView) mView.findViewById(R.id.image_preview);
mVideoPreview = (VideoView) mView.findViewById(R.id.video_preview);
mVideoPreview.setOnTouchListener(this);
mMediaController = (MediaControlView) mView.findViewById(R.id.media_controller);
mMultiView = (RelativeLayout) mView.findViewById(R.id.multi_view);
setupMultiView(mView);
setMultiListLoadingMessage();
return mView;
}
protected void setupMultiView(View view) {
mMultiListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
mMultiListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
mMultiListHeadline = (TextView) view.findViewById(R.id.empty_list_view_headline);
mMultiListIcon = (ImageView) view.findViewById(R.id.empty_list_icon);
mMultiListProgress = (ProgressBar) view.findViewById(R.id.empty_list_progress);
}
private void setMultiListLoadingMessage() {
if (mMultiView != null) {
mMultiListHeadline.setText(R.string.file_list_loading);
mMultiListMessage.setText("");
mMultiListIcon.setVisibility(View.GONE);
mMultiListProgress.setVisibility(View.VISIBLE);
}
}
public void setMessageForMultiList(String headline, @StringRes int message, @DrawableRes int icon) {
if (mMultiListContainer != null && mMultiListMessage != null) {
mMultiListHeadline.setText(headline);
mMultiListMessage.setText(message);
mMultiListIcon.setImageResource(icon);
mMultiListIcon.setVisibility(View.VISIBLE);
mMultiListProgress.setVisibility(View.GONE);
}
}
/**
* {@inheritDoc}
*/
@ -197,6 +244,7 @@ public class PreviewMediaFragment extends FileFragment implements
mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
}
if (file != null && file.isDown()) {
if (MimeTypeUtil.isVideo(file)) {
mVideoPreview.setVisibility(View.VISIBLE);
@ -455,6 +503,8 @@ public class PreviewMediaFragment extends FileFragment implements
@Override
public void onPrepared(MediaPlayer vp) {
Log_OC.v(TAG, "onPrepared");
mMultiView.setVisibility(View.GONE);
mPreviewContainer.setVisibility(View.VISIBLE);
mVideoPreview.seekTo(mSavedPlaybackPosition);
if (mAutoplay) {
mVideoPreview.start();
@ -492,20 +542,12 @@ public class PreviewMediaFragment extends FileFragment implements
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
mPreviewContainer.setVisibility(View.GONE);
if (mVideoPreview.getWindowToken() != null) {
String message = MediaService.getMessageForMediaError(
getActivity(), what, extra);
new AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton(android.R.string.VideoView_error_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
VideoHelper.this.onCompletion(null);
}
})
.setCancelable(false)
.show();
mMultiView.setVisibility(View.VISIBLE);
setMessageForMultiList(message, R.string.preview_sorry, R.drawable.file_movie);
}
return true;
}
@ -556,7 +598,7 @@ public class PreviewMediaFragment extends FileFragment implements
if (event.getX() / Resources.getSystem().getDisplayMetrics().density > 24.0) {
startFullScreenVideo();
}
return true;
return true;
}
return false;
}
@ -612,11 +654,11 @@ public class PreviewMediaFragment extends FileFragment implements
}
getActivity().bindService( new Intent(getActivity(),
MediaService.class),
mMediaServiceConnection,
mMediaServiceConnection,
Context.BIND_AUTO_CREATE);
// follow the flow in MediaServiceConnection#onServiceConnected(...)
}
/** Defines callbacks for service binding, passed to bindService() */
private class MediaServiceConnection implements ServiceConnection {
@ -657,7 +699,7 @@ public class PreviewMediaFragment extends FileFragment implements
else {
Toast.makeText(
getActivity(),
"No media controller to release when disconnected from media service",
"No media controller to release when disconnected from media service",
Toast.LENGTH_SHORT).show();
}
mMediaServiceBinder = null;

View file

@ -22,15 +22,16 @@ package com.owncloud.android.ui.preview;
import android.accounts.Account;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
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.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.owncloud.android.R;
@ -39,7 +40,6 @@ import com.owncloud.android.files.FileMenuFilter;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.LoadingDialog;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.utils.MimeTypeUtil;
@ -65,6 +65,15 @@ public class PreviewTextFragment extends FileFragment {
private TextView mTextPreview;
private TextLoadAsyncTask mTextLoadTask;
private RelativeLayout mMultiView;
protected LinearLayout mMultiListContainer;
protected TextView mMultiListMessage;
protected TextView mMultiListHeadline;
protected ImageView mMultiListIcon;
protected ProgressBar mMultiListProgress;
/**
* Creates an empty fragment for previews.
* <p/>
@ -93,9 +102,33 @@ public class PreviewTextFragment extends FileFragment {
mTextPreview = (TextView) ret.findViewById(R.id.text_preview);
mMultiView = (RelativeLayout) ret.findViewById(R.id.multi_view);
setupMultiView(ret);
setMultiListLoadingMessage();
return ret;
}
protected void setupMultiView(View view) {
mMultiListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
mMultiListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
mMultiListHeadline = (TextView) view.findViewById(R.id.empty_list_view_headline);
mMultiListIcon = (ImageView) view.findViewById(R.id.empty_list_icon);
mMultiListProgress = (ProgressBar) view.findViewById(R.id.empty_list_progress);
}
private void setMultiListLoadingMessage() {
if (mMultiView != null) {
mMultiListHeadline.setText(R.string.file_list_loading);
mMultiListMessage.setText("");
mMultiListIcon.setVisibility(View.GONE);
mMultiListProgress.setVisibility(View.VISIBLE);
}
}
/**
* {@inheritDoc}
*/
@ -168,7 +201,6 @@ public class PreviewTextFragment extends FileFragment {
@Override
protected void onPreExecute() {
showLoadingDialog();
}
@Override
@ -224,39 +256,12 @@ public class PreviewTextFragment extends FileFragment {
textView.setVisibility(View.VISIBLE);
}
dismissLoadingDialog();
}
/**
* Show loading dialog
*/
public void showLoadingDialog() {
// only once
Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
LoadingDialog loading = null;
if (frag == null) {
// Construct dialog
loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
FragmentManager fm = getActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
loading.show(ft, DIALOG_WAIT_TAG);
} else {
loading = (LoadingDialog) frag;
loading.setShowsDialog(true);
if (mMultiView != null) {
mMultiView.setVisibility(View.GONE);
}
}
/**
* Dismiss loading dialog
*/
public void dismissLoadingDialog() {
final Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
if (frag != null) {
LoadingDialog loading = (LoadingDialog) frag;
loading.dismissAllowingStateLoss();
}
}
}
/**
@ -426,7 +431,6 @@ public class PreviewTextFragment extends FileFragment {
Log_OC.e(TAG, "onStop");
if (mTextLoadTask != null) {
mTextLoadTask.cancel(Boolean.TRUE);
mTextLoadTask.dismissLoadingDialog();
}
}

View file

@ -10,8 +10,6 @@
package third_parties.michaelOrtiz;
import com.owncloud.android.ui.preview.ImageViewCustom;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
@ -37,6 +35,8 @@ import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.OverScroller;
import android.widget.Scroller;
import com.owncloud.android.ui.preview.ImageViewCustom;
/**
* Extends Android ImageView to include pinch zooming, panning, fling and double tap zoom.
*/

View file

@ -19,46 +19,70 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".ui.fragment.FilePreviewFragment">
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".ui.fragment.FilePreviewFragment">
<RelativeLayout
android:id="@+id/file_preview_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:background="@color/black">
<FrameLayout
android:id="@+id/visual_area"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="@+id/media_controller"
android:layout_alignParentTop="true"
>
<ImageView
android:id="@+id/image_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="@dimen/standard_margin"
android:contentDescription="@string/preview_image_description"
android:src="@drawable/logo"/>
<VideoView
android:id="@+id/video_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
<com.owncloud.android.media.MediaControlView
android:id="@id/media_controller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="@dimen/standard_margin"
/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/multi_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/empty_list"/>
</ScrollView>
</RelativeLayout>
<FrameLayout
android:id="@+id/visual_area"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:layout_above="@+id/media_controller"
>
<ImageView
android:id="@+id/image_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/standard_margin"
android:layout_gravity="center"
android:contentDescription="@string/preview_image_description"
android:src="@drawable/logo" />
<VideoView
android:id="@+id/video_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
<com.owncloud.android.media.MediaControlView
android:id="@id/media_controller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="@dimen/standard_margin"
/>
</RelativeLayout>

View file

@ -65,6 +65,7 @@
android:layout_height="wrap_content"
android:paddingEnd="@dimen/standard_quarter_padding"
android:text="@string/placeholder_media_time"
android:textColor="@color/white"
/>
<SeekBar
@ -74,7 +75,11 @@
android:layout_weight="1"
android:layout_height="@dimen/seek_bar_height"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true" />
android:layout_alignParentEnd="true"
android:progressDrawable="@color/white"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:splitTrack="false"/>
<TextView android:id="@+id/totalTimeText"
android:textSize="@dimen/two_line_secondary_text_size"
@ -86,6 +91,7 @@
android:layout_height="wrap_content"
android:paddingStart="@dimen/standard_quarter_padding"
android:text="@string/placeholder_media_time"
android:textColor="@color/white"
/>
</LinearLayout>

View file

@ -31,36 +31,32 @@
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:context=".ui.fragment.PreviewImageFragment" >
android:animateLayoutChanges="true">
<ProgressBar
android:id="@+id/progressWheel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateOnly="true"
android:layout_centerInParent="true"
/>
<third_parties.michaelOrtiz.TouchImageViewCustom
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/zero"
android:layout_centerInParent="true"
android:layout_margin="@dimen/zero"
android:contentDescription="@string/preview_image_description"
android:src="@drawable/image_fail" />
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_margin="@dimen/preview_image_fragment_display_text_margin"
android:text="@string/placeholder_sentence"
android:textColor="@color/owncloud_blue_bright"
/>
android:src="@drawable/image_fail"/>
<RelativeLayout
android:id="@+id/multi_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/empty_list"/>
</ScrollView>
</RelativeLayout>
</RelativeLayout>

View file

@ -21,11 +21,31 @@
android:layout_height="match_parent"
android:fillViewport="true">
<TextView
android:id="@+id/text_preview"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/standard_padding"
android:textIsSelectable="true"
android:visibility="gone"/>
android:layout_height="match_parent">
<TextView
android:id="@+id/text_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/standard_padding"
android:textIsSelectable="true"
android:visibility="gone"/>
<RelativeLayout
android:id="@+id/multi_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/empty_list"/>
</ScrollView>
</RelativeLayout>
</RelativeLayout>
</ScrollView>

View file

@ -352,7 +352,7 @@
<string name="preview_sorry">Sorry about that!</string>
<string name="preview_image_description">Image preview</string>
<string name="preview_image_error_unknown_format">This image cannot be shown</string>
<string name="preview_image_error_unknown_format">Image can\'t be shown</string>
<string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local folder</string>
<string name="prefs_instant_upload_path_title">Instant upload folder</string>

View file

@ -120,16 +120,17 @@
<!-- separat translucent action bar style -->
<style name="Theme.ownCloud.Overlay" parent="style/Theme.ownCloud">
<item name="android:actionBarStyle">@style/Theme.ownCloud.Overlay.ActionBar</item>
<item name="windowActionBarOverlay">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowFullscreen">true</item>
<!-- Support library compatibility -->
<item name="actionBarStyle">@style/Theme.ownCloud.Overlay.ActionBar</item>
<item name="windowActionBarOverlay">true</item>
</style>
<!-- ACTION BAR STYLES -->
<style name="Theme.ownCloud.Overlay.ActionBar" parent="@style/Widget.AppCompat.ActionBar">
<item name="android:background">@color/owncloud_blue_transparent</item>
<item name="android:windowActionBarOverlay">true</item>
<!-- Support library compatibility -->
<item name="background">@color/owncloud_blue_transparent</item>
<item name="windowActionBarOverlay">true</item>