/*
* Copyright (C) 2014 Freddie (Musenkishi) Lust-Hed
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.musenkishi.wally.activities;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.musenkishi.paletteloader.PaletteLoader;
import com.musenkishi.paletteloader.PaletteRequest;
import com.musenkishi.wally.R;
import com.musenkishi.wally.anim.interpolator.EaseInOutBezierInterpolator;
import com.musenkishi.wally.base.BaseActivity;
import com.musenkishi.wally.base.WallyApplication;
import com.musenkishi.wally.dataprovider.DataProvider;
import com.musenkishi.wally.dataprovider.FileManager;
import com.musenkishi.wally.dataprovider.models.DataProviderError;
import com.musenkishi.wally.dataprovider.models.SaveImageRequest;
import com.musenkishi.wally.fragments.SearchFragment;
import com.musenkishi.wally.models.Author;
import com.musenkishi.wally.models.Image;
import com.musenkishi.wally.models.ImagePage;
import com.musenkishi.wally.models.Size;
import com.musenkishi.wally.models.Tag;
import com.musenkishi.wally.observers.FileReceiver;
import com.musenkishi.wally.util.Blur;
import com.musenkishi.wally.views.FlowLayout;
import com.musenkishi.wally.views.ObservableScrollView;
import uk.co.senab.photoview.PhotoViewAttacher;
import static com.musenkishi.wally.views.ObservableScrollView.ScrollViewListener;
/**
* Activity for showing image and any other information about the image.
* Created by Musenkishi on 2014-03-05 20:23.
*/
public class ImageDetailsActivity extends BaseActivity implements Handler.Callback {
private static final int MSG_GET_PAGE = 130;
private static final int MSG_PAGE_FETCHED = 417892;
private static final int MSG_PAGE_ERROR = 417891;
private static final int MSG_IMAGE_REQUEST_READY_FOR_SETTING = 987484;
private static final int MSG_IMAGE_REQUEST_SAVED = 987483;
private static final int MSG_IMAGE_REQUEST_SAVING = 987482;
private static final int MSG_SAVE_TO_FILE = 987486;
private static final int MSG_RENDER_PALETTE = 987487;
private static final int MSG_SET_IMAGE_AND_PALETTE = 987488;
private static final int MSG_SCROLL_UP_SCROLLVIEW = 987489;
public static final String TAG = "com.musenkishi.wally.ImageDetailsActivity";
private static final String STATE_IMAGE_PAGE = "ImageDetailsActivity.ImagePage";
public static final String INTENT_EXTRA_IMAGE = TAG + ".Intent.Image";
public static final String INTENT_EXTRA_TAG_NAME = TAG + ".Intent.Tag.Name";
public static final int REQUEST_EXTRA_TAG = 13134;
private Handler uiHandler;
private Handler backgroundHandler;
private ObservableScrollView scrollView;
private ImageView photoView;
private PhotoViewAttacher photoViewAttacher;
private ImageButton buttonFullscreen;
private ProgressBar loader;
private Uri pageUri;
private TextView textViewUploader;
private TextView textViewUploadDate;
private TextView textViewSource;
private TextView textViewResolution;
private TextView textViewCategory;
private TextView textViewRating;
private FlowLayout flowLayoutTags;
private Button buttonSetAs;
private Button buttonSave;
private ImagePage imagePage;
private ViewGroup imageHolder;
private ViewGroup photoLayoutHolder;
private int currentHandlerCode;
private Palette palette;
private ViewGroup toolbar;
private ViewGroup specsLayout;
private Size imageSize;
private boolean isInFullscreen = false;
private View detailsViewGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_details);
setToolbar((Toolbar) findViewById(R.id.toolbar));
if (getToolbar() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getToolbar().setPadding(0, getStatusBarHeight(), 0, 0);
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("");
}
final Intent intent = getIntent();
String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
pageUri = Uri.parse(intent.getDataString());
if ("wally".equalsIgnoreCase(pageUri.getScheme())){
pageUri = pageUri.buildUpon().scheme("http").build();
}
}
setupViews();
setupHandlers();
Size size = new Size(16,9);
if (intent.hasExtra(INTENT_EXTRA_IMAGE)) {
final Image image = intent.getParcelableExtra(INTENT_EXTRA_IMAGE);
final Bitmap thumbBitmap = WallyApplication.getBitmapThumb();
if (thumbBitmap != null) {
size = fitToWidthAndKeepRatio(image.getWidth(), image.getHeight());
imageSize = size;
photoView.getLayoutParams().width = size.getWidth();
photoView.getLayoutParams().height = size.getHeight();
Bitmap blurBitMap;
try {
blurBitMap = Blur.apply(imageHolder.getContext(), thumbBitmap);
} catch (ArrayIndexOutOfBoundsException e) {
//Blur couldn't be applied. Show regular thumbnail instead.
blurBitMap = thumbBitmap;
}
photoView.setImageBitmap(blurBitMap);
}
}
setupPaddings(size, false);
if (savedInstanceState == null) {
getPage(pageUri.toString());
} else if (savedInstanceState.containsKey(STATE_IMAGE_PAGE)){
imagePage = savedInstanceState.getParcelable(STATE_IMAGE_PAGE);
}
if (imagePage != null) {
Message msgObj = uiHandler.obtainMessage();
msgObj.what = MSG_PAGE_FETCHED;
msgObj.obj = imagePage;
uiHandler.sendMessage(msgObj);
} else {
getPage(pageUri.toString());
}
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
private void setupPaddings(final Size size, boolean animate) {
int animationDuration = animate ? 300 : 0;
final int sidePadding = getResources().getDimensionPixelSize(R.dimen.activity_details_scrollview_side_padding);
int fabPadding = getResources().getDimensionPixelSize(R.dimen.fab_padding_positive);
int minimumAllowedHeight = fabPadding;
if (size.getHeight() < minimumAllowedHeight) {
size.setHeight(size.getHeight());
ValueAnimator valueAnimator = ValueAnimator.ofInt(photoLayoutHolder.getPaddingTop());
valueAnimator.setInterpolator(new EaseInOutBezierInterpolator());
valueAnimator.setDuration(animationDuration);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
photoLayoutHolder.setPadding(
0,
(Integer) valueAnimator.getAnimatedValue(),
0,
0
);
}
});
valueAnimator.start();
} else {
photoLayoutHolder.setPadding(0, 0, 0, 0 );
}
scrollView.setPadding(0, 0, 0, -fabPadding );
specsLayout.setPadding(0, 0, 0, fabPadding);
ValueAnimator valueAnimator = ValueAnimator.ofInt(detailsViewGroup.getPaddingTop(), size.getHeight());
valueAnimator.setInterpolator(new EaseInOutBezierInterpolator());
valueAnimator.setDuration(animationDuration);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
detailsViewGroup.setPadding(sidePadding,
(Integer) valueAnimator.getAnimatedValue(),
sidePadding,
detailsViewGroup.getPaddingBottom());
}
});
valueAnimator.start();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if (imagePage != null) {
outState.putParcelable(STATE_IMAGE_PAGE, imagePage);
}
super.onSaveInstanceState(outState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.image_details, menu);
MenuItem shareMenuItem = menu.findItem(R.id.action_share);
if (shareMenuItem != null) {
ShareActionProvider shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, pageUri.toString());
shareActionProvider.setShareIntent(shareIntent);
shareMenuItem.setIcon(R.drawable.ic_action_share);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_share:
return false;
case R.id.action_open:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, pageUri);
startActivity(browserIntent);
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPause() {
Drawable heart = getResources().getDrawable(R.drawable.ic_action_saved);
heart.clearColorFilter();
super.onPause();
}
@Override
protected void onDestroy() {
Glide.clear(photoView);
backgroundHandler.removeCallbacksAndMessages(null);
uiHandler.removeCallbacksAndMessages(null);
backgroundHandler.getLooper().quit();
super.onDestroy();
}
private void setupViews() {
scrollView = (ObservableScrollView) findViewById(R.id.image_details_scrollview);
imageHolder = (ViewGroup) findViewById(R.id.image_details_imageview_holder);
photoView = (ImageView) findViewById(R.id.image_details_imageview);
buttonFullscreen = (ImageButton) findViewById(R.id.image_details_button_fullscreen);
loader = (ProgressBar) findViewById(R.id.image_details_loader);
textViewUploader = (TextView) findViewById(R.id.image_details_uploader);
textViewUploadDate = (TextView) findViewById(R.id.image_details_upload_date);
textViewSource = (TextView) findViewById(R.id.image_details_source);
textViewResolution = (TextView) findViewById(R.id.image_details_resolution);
textViewCategory = (TextView) findViewById(R.id.image_details_category);
textViewRating = (TextView) findViewById(R.id.image_details_rating);
flowLayoutTags = (FlowLayout) findViewById(R.id.image_details_tags_layout);
buttonSetAs = (Button) findViewById(R.id.toolbar_set_as);
buttonSave = (Button) findViewById(R.id.toolbar_save);
toolbar = (ViewGroup) findViewById(R.id.image_details_toolbar);
photoLayoutHolder = (ViewGroup) findViewById(R.id.image_details_photo_layout_holder);
specsLayout = (ViewGroup) findViewById(R.id.image_details_specs);
detailsViewGroup = findViewById(R.id.image_details_layout);
specsLayout.setAlpha(0.0f);
int sidePadding = getResources().getDimensionPixelSize(R.dimen.activity_details_scrollview_side_padding);
int fabPadding = getResources().getDimensionPixelSize(R.dimen.fab_padding_positive);
scrollView.setPadding(0, 0, 0, -fabPadding);
specsLayout.setPadding(0, 0, 0, fabPadding);
photoLayoutHolder.setPadding(0, 0, 0, 0);
detailsViewGroup.setPadding(
sidePadding,
detailsViewGroup.getPaddingTop(),
sidePadding,
detailsViewGroup.getPaddingBottom()
);
}
@Override
public void onBackPressed() {
if (isInFullscreen()) {
toggleZoomImage();
} else {
super.onBackPressed();
}
}
private Size fitToWidthAndKeepRatio(int width, int height) {
WindowManager win = getWindowManager();
Display d = win.getDefaultDisplay();
int displayWidth = d.getWidth(); // Width of the actual device
int fittedHeight = height;
int fittedWidth = width;
fittedHeight = displayWidth * fittedHeight / fittedWidth;
fittedWidth = displayWidth;
return new Size(fittedWidth, fittedHeight);
}
private void enableParallaxEffect(ObservableScrollView scrollView, final View parallaxingView) {
scrollView.setScrollViewListener(new ScrollViewListener() {
@Override
public void onScrollChanged(ObservableScrollView scrollView,
int x, int y, int oldx, int oldy) {
WindowManager win = getWindowManager();
Display d = win.getDefaultDisplay();
int displayHeight = d.getHeight(); // Height of the actual device
if (imageSize.getHeight() > displayHeight && photoViewAttacher != null) {
float[] values = new float[9];
photoViewAttacher.getDrawMatrix().getValues(values);
float imageHeight = imageSize.getHeight();
float diff = imageHeight/displayHeight;
if (y > oldy) {
diff = -diff;
}
photoViewAttacher.onDrag(0, diff);
} else {
float pY = -(y / 3.0f);
parallaxingView.setTranslationY(pY);
}
}
});
}
private void saveImage(boolean notifyUser) {
if (notifyUser) {
uiHandler.sendEmptyMessage(MSG_IMAGE_REQUEST_SAVING);
}
Message msgObj = backgroundHandler.obtainMessage();
msgObj.what = MSG_SAVE_TO_FILE;
msgObj.arg1 = MSG_IMAGE_REQUEST_SAVED;
backgroundHandler.sendMessage(msgObj);
}
private void setImageAsWallpaperPicker(Uri path) {
Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
intent.setType("image/*");
MimeTypeMap map = MimeTypeMap.getSingleton();
String mimeType = map.getMimeTypeFromExtension("png");
intent.setDataAndType(path, mimeType);
intent.putExtra("mimeType", mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intent, getString(R.string.action_set_as)));
}
private void getPage(String url) {
Message msgGetPage = backgroundHandler.obtainMessage();
msgGetPage.what = MSG_GET_PAGE;
msgGetPage.obj = url;
backgroundHandler.sendMessage(msgGetPage);
}
private void setupHandlers() {
HandlerThread handlerThread = new HandlerThread("background");
handlerThread.start();
backgroundHandler = new Handler(handlerThread.getLooper(), this);
uiHandler = new Handler(getMainLooper(), this);
}
private void renderTags(Bitmap bitmap) {
if (this.palette == null && flowLayoutTags.getChildCount() > 0) {
for (int i = 0; i < flowLayoutTags.getChildCount(); i++) {
View tagView = flowLayoutTags.getChildAt(i);
TextView tagTextView = (TextView) tagView.findViewById(R.id.tag_item_text);
PaletteLoader.with(this, imagePage.imagePath().toString())
.load(bitmap)
.setPaletteRequest(new PaletteRequest(
PaletteRequest.SwatchType.REGULAR_MUTED,
PaletteRequest.SwatchColor.BACKGROUND))
.into(tagTextView);
}
}
}
private void renderColors(Bitmap bitmap) {
//Could already be rendered b.c. duplicate callback by Glide.
if (this.palette == null) {
PaletteLoader.with(this, imagePage.imagePath().toString())
.load(bitmap)
.setPaletteRequest(new PaletteRequest(
PaletteRequest.SwatchType.DARK_MUTED,
PaletteRequest.SwatchColor.BACKGROUND))
.setListener(new PaletteLoader.OnPaletteRenderedListener() {
@Override
public void onRendered(Palette palette) {
setColors(palette);
}
})
.into(findViewById(R.id.image_details_root));
}
}
private void setColors(Palette palette){
this.palette = palette;
hideLoader();
Palette.Swatch swatch = PaletteRequest.getBestSwatch(palette, palette.getDarkMutedSwatch());
if (swatch != null) {
photoLayoutHolder.setBackgroundColor(swatch.getRgb());
Drawable floatingButtonBackground = getResources()
.getDrawable(R.drawable.floating_action_button);
Drawable floatingButtonIcon = getResources().getDrawable(R.drawable.ic_mask_fullscreen);
Palette.Swatch fabSwatch = PaletteRequest.getBestSwatch(palette,
palette.getVibrantSwatch());
if (fabSwatch != null) {
floatingButtonBackground.setColorFilter(fabSwatch.getRgb(),
PorterDuff.Mode.MULTIPLY);
floatingButtonIcon.setColorFilter(fabSwatch.getBodyTextColor(),
PorterDuff.Mode.MULTIPLY);
}
buttonFullscreen.setBackgroundDrawable(floatingButtonBackground);
buttonFullscreen.setImageDrawable(floatingButtonIcon);
buttonFullscreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleZoomImage();
}
});
toolbar.setBackgroundColor(swatch.getRgb());
buttonSetAs.setTextColor(swatch.getBodyTextColor());
buttonSave.setTextColor(swatch.getBodyTextColor());
setToolbarClickListeners();
animateToolbar(View.VISIBLE);
}
}
/**
* Animations animations animations.
* @param visibility if VISIBLE, expands toolbar.
*/
private void animateToolbar(int visibility) {
float from;
float to;
int toolbarOffset;
int fabOffset;
if (visibility == View.VISIBLE) {
from = 0.0f;
to = 1.0f;
fabOffset = 200;
toolbarOffset = 0;
} else {
from = 1.0f;
to = 0.0f;
fabOffset = 0;
toolbarOffset = 200;
}
buttonFullscreen.animate()
.scaleX(to)
.scaleY(to)
.setDuration(400)
.setStartDelay(fabOffset)
.setInterpolator(new EaseInOutBezierInterpolator())
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
buttonFullscreen.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
})
.start();
int toolbarFrom;
int toolbarTo;
if (from > 0.0f) {
toolbarFrom = getResources().getDimensionPixelSize(R.dimen.details_toolbar_height);
toolbarTo = 0;
} else {
toolbarFrom = 0;
toolbarTo = getResources().getDimensionPixelSize(R.dimen.details_toolbar_height);
}
ValueAnimator valueAnimator = ValueAnimator.ofInt(toolbarFrom, toolbarTo);
valueAnimator.setDuration(400);
valueAnimator.setStartDelay(toolbarOffset);
valueAnimator.setInterpolator(new EaseInOutBezierInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
RelativeLayout.LayoutParams toolbarParams =
(RelativeLayout.LayoutParams) toolbar.getLayoutParams();
toolbarParams.height = val;
toolbar.setLayoutParams(toolbarParams);
}
});
valueAnimator.start();
}
private void setToolbarClickListeners() {
buttonSetAs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msgObj = backgroundHandler.obtainMessage();
msgObj.what = MSG_SAVE_TO_FILE;
msgObj.arg1 = MSG_IMAGE_REQUEST_READY_FOR_SETTING;
backgroundHandler.sendMessage(msgObj);
}
});
updateSaveButton();
}
private void updateSaveButton() {
if (imagePage != null) {
FileManager fileManager = new FileManager();
boolean imageExists = fileManager.fileExists(imagePage.imageId());
if (imageExists) {
buttonSave.setClickable(false);
buttonSave.setText(R.string.saved);
buttonSave.setAlpha(0.5f);
} else {
if (!buttonSave.isClickable()){
buttonSave.setClickable(true);
buttonSave.setText(R.string.action_save);
}
buttonSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.setClickable(false);
saveImage(true);
}
});
}
}
}
private void saveToFile(final int handlerCode) {
currentHandlerCode = handlerCode;
SaveImageRequest saveImageRequest = WallyApplication
.getDataProviderInstance()
.downloadImageIfNeeded(
imagePage.imagePath(),
pageUri.getLastPathSegment(),
getResources().getString(R.string.notification_title_image_saving));
if (saveImageRequest.getDownloadID() != null){
WallyApplication.getDownloadIDs().put(saveImageRequest.getDownloadID(), pageUri.getLastPathSegment());
} else {
handleSavedImageData(saveImageRequest.getFilePath());
}
}
@Override
protected void handleReceivedIntent(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0L);
if (WallyApplication.getDownloadIDs().containsKey(id)){
WallyApplication.getDownloadIDs().remove(id);
updateSaveButton();
if (palette != null && palette.getVibrantSwatch() != null) {
startHeartPopoutAnimation(buttonSave, palette.getVibrantSwatch().getBodyTextColor());
} else {
startHeartPopoutAnimation(buttonSave, Color.WHITE);
}
String filename = pageUri.getLastPathSegment();
handleSavedImageData(WallyApplication.getDataProviderInstance().getFilePath(filename));
}
}
private void handleSavedImageData(Uri filePath) {
if (filePath != null && filePath.getPath() != null) {
Message msgObj = uiHandler.obtainMessage();
msgObj.what = currentHandlerCode;
msgObj.obj = filePath;
uiHandler.sendMessage(msgObj);
MediaScannerConnection.scanFile(getApplicationContext(),
new String[]{filePath.getPath()},
null,
new MediaScannerConnection.MediaScannerConnectionClient() {
@Override
public void onMediaScannerConnected() {
}
@Override
public void onScanCompleted(String path, Uri uri) {
getApplication().sendBroadcast(new Intent(FileReceiver.GET_FILES));
}
}
);
}
}
private void showLoader() {
loader.animate().alpha(1.0f).setDuration(300).start();
}
private void hideLoader() {
loader.animate().alpha(0.0f).setDuration(300).start();
}
/**
* Returns true if fullscreen mode is currently active.
*/
private boolean isInFullscreen() {
return isInFullscreen;
}
/**
* Animations animations animations.
*/
private void toggleZoomImage() {
int animationDuration = 400;
if (isInFullscreen()){
scrollView.smoothScrollTo(0, (Integer) scrollView.getTag());
if (photoViewAttacher != null) {
photoViewAttacher.cleanup();
photoViewAttacher = null;
photoView.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
} else {
scrollView.setTag(scrollView.getScrollY());
scrollView.smoothScrollTo(0, 0);
if (photoViewAttacher == null) {
photoViewAttacher = new PhotoViewAttacher(photoView);
photoViewAttacher.setZoomable(true);
photoViewAttacher.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
}
if (getSupportActionBar() != null) {
getToolbar().animate()
.translationY(isInFullscreen() ? 0.0f : -getToolbar().getMeasuredHeight())
.alpha(isInFullscreen() ? 1.0f : 0.0f)
.setDuration(500)
.setInterpolator(new EaseInOutBezierInterpolator())
.start();
}
findViewById(R.id.image_details_protective_shadow).animate()
.alpha(isInFullscreen() ? 1.0f : 0.0f)
.setDuration(500)
.setInterpolator(new EaseInOutBezierInterpolator())
.start();
int minimumAllowedHeight = getToolbar().getMeasuredHeight()
+ getResources().getDimensionPixelSize(R.dimen.fab_padding_positive);
if (imageSize.getHeight() < minimumAllowedHeight) {
int topFrom;
int topTo;
if (isInFullscreen()) {
topFrom = 0;
topTo = getToolbar().getMeasuredHeight();
} else {
topFrom = photoLayoutHolder.getPaddingTop();
topTo = 0;
}
ValueAnimator topValueAnimator = ValueAnimator.ofInt(topFrom, topTo);
topValueAnimator.setDuration(animationDuration);
topValueAnimator.setInterpolator(new EaseInOutBezierInterpolator());
topValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
photoLayoutHolder.setPadding(
photoLayoutHolder.getPaddingLeft(),
val,
photoLayoutHolder.getPaddingRight(),
photoLayoutHolder.getPaddingBottom()
);
}
});
topValueAnimator.start();
}
if (photoLayoutHolder.getTranslationY() != 0.0f) {
photoLayoutHolder.animate()
.translationY(0.0f)
.setInterpolator(new EaseInOutBezierInterpolator())
.setDuration(animationDuration)
.start();
}
WindowManager win = getWindowManager();
Display d = win.getDefaultDisplay();
int from = photoView.getMeasuredHeight();
int to = isInFullscreen() ? imageSize.getHeight() : d.getHeight();
ValueAnimator valueAnimator = ValueAnimator.ofInt(from, to);
valueAnimator.setDuration(animationDuration);
valueAnimator.setInterpolator(new EaseInOutBezierInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
RelativeLayout.LayoutParams toolbarParams =
(RelativeLayout.LayoutParams) photoView.getLayoutParams();
toolbarParams.height = val;
photoView.setLayoutParams(toolbarParams);
}
});
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationEnd(Animator animator) {
if (photoViewAttacher != null) {
photoViewAttacher.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
@Override
public void onPhotoTap(View view, float v, float v2) {
toggleZoomImage();
}
});
}
}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
});
valueAnimator.start();
int scrollTo = isInFullscreen() ? 0 : d.getHeight();
scrollView.animate()
.y(scrollTo)
.setDuration(animationDuration)
.setInterpolator(new EaseInOutBezierInterpolator())
.start();
isInFullscreen = !isInFullscreen;
}
private void scrollUpToolbarIfNeeded() {
Display thisDisplay = getWindowManager().getDefaultDisplay();
int screenHeight = thisDisplay.getHeight();
int emptySpace = detailsViewGroup.getPaddingTop();
int targetHeight = emptySpace - ((screenHeight/3)*2);
int navBarHeight = 0;
if (imageSize.getHeight() > (screenHeight - navBarHeight)) {
Message msgObj = uiHandler.obtainMessage();
msgObj.what = MSG_SCROLL_UP_SCROLLVIEW;
msgObj.arg1 = targetHeight;
uiHandler.sendMessageDelayed(msgObj, 500);
}
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_GET_PAGE:
String url = (String) msg.obj;
if (url != null) {
WallyApplication.getDataProviderInstance().getPageData(
url,
new DataProvider.OnPageReceivedListener() {
@Override
public void onPageReceived(ImagePage imagePage) {
Message msgObj = uiHandler.obtainMessage();
msgObj.what = MSG_PAGE_FETCHED;
msgObj.obj = imagePage;
uiHandler.sendMessage(msgObj);
}
@Override
public void onError(DataProviderError error) {
Message msgObj = uiHandler.obtainMessage();
msgObj.what = MSG_PAGE_ERROR;
msgObj.obj = error;
uiHandler.sendMessage(msgObj);
}
});
}
break;
case MSG_SAVE_TO_FILE:
int what = msg.arg1;
saveToFile(what);
break;
case MSG_PAGE_FETCHED:
imagePage = (ImagePage) msg.obj;
if (imagePage != null) {
textViewUploader.setText(imagePage.uploader());
textViewUploadDate.setText(imagePage.uploadDate());
textViewSource.setText(imagePage.author().name());
if (imagePage.author().page() != Uri.EMPTY) {
textViewSource.setTextColor(getResources()
.getColor(R.color.Holo_Blue_Dark)
);
textViewSource.setTag(imagePage.author());
textViewSource.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Author author = (Author) v.getTag();
if (author.page() != Uri.EMPTY) {
Intent browserIntent = new Intent(
Intent.ACTION_VIEW,
author.page()
);
startActivity(browserIntent);
}
}
});
}
textViewResolution.setText(imagePage.resolution());
textViewCategory.setText(imagePage.category());
textViewRating.setText(imagePage.rating());
final String imageUrl = imagePage.imagePath().toString();
if (imagePage.tags().size() > 0) {
flowLayoutTags.removeAllViews();
for (final Tag tag : imagePage.tags()) {
View tagView = getLayoutInflater().inflate(R.layout.view_tag_item, flowLayoutTags, false);
TextView tagTextView = (TextView) tagView.findViewById(R.id.tag_item_text);
tagTextView.setText(tag.name());
flowLayoutTags.addView(tagView);
tagTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
WallyApplication.getSearchFragmentMessages().put(SearchFragment.EXTRA_MESSAGE_TAG, tag.name());
Intent intent = new Intent();
setResult(RESULT_OK, intent);
ImageDetailsActivity.this.finish();
}
});
}
} else {
findViewById(R.id.image_details_tags_title).setVisibility(View.GONE);
flowLayoutTags.setVisibility(View.GONE);
}
Glide.with(getApplicationContext())
.load(imageUrl)
.placeholder(photoView.getDrawable())
.fitCenter()
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e,
String model,
Target<GlideDrawable> target,
boolean isFirstResource) {
hideLoader();
//TODO: maybe show a retry button?
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource,
String model,
Target<GlideDrawable> target,
boolean isFromMemoryCache,
boolean isFirstResource) {
photoView.setScaleType(ImageView.ScaleType.CENTER_CROP);
renderTags(
((GlideBitmapDrawable) resource.getCurrent())
.getBitmap()
);
renderColors(
((GlideBitmapDrawable) resource.getCurrent())
.getBitmap()
);
photoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggleZoomImage();
}
});
hideLoader();
Size size = fitToWidthAndKeepRatio(
imagePage.getImageWidth(),
imagePage.getImageHeight()
);
imageSize = size;
setupPaddings(size, true);
scrollUpToolbarIfNeeded();
return false;
}
})
.into(photoView);
specsLayout.setAlpha(1.0f);
specsLayout.scheduleLayoutAnimation();
enableParallaxEffect(scrollView, photoLayoutHolder);
}
break;
case MSG_PAGE_ERROR:
DataProviderError dataProviderError = (DataProviderError) msg.obj;
if (dataProviderError != null) {
Toast.makeText(ImageDetailsActivity.this, dataProviderError.getHttpStatusCode()
+ ": "
+ dataProviderError.getMessage(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ImageDetailsActivity.this,
getString(R.string.toast_error_default),
Toast.LENGTH_SHORT).show();
}
break;
case MSG_IMAGE_REQUEST_READY_FOR_SETTING:
Uri savedImageDataForWallpaper = (Uri) msg.obj;
if (savedImageDataForWallpaper != null) {
setImageAsWallpaperPicker(savedImageDataForWallpaper);
}
break;
case MSG_IMAGE_REQUEST_SAVED:
updateSaveButton();
break;
case MSG_IMAGE_REQUEST_SAVING:
if (buttonSave != null) {
buttonSave.setText(getString(R.string.saving));
buttonSave.setAlpha(0.50f);
}
break;
case MSG_RENDER_PALETTE:
Bitmap bitmap1 = (Bitmap) msg.obj;
Palette palette = Palette.generate(bitmap1);
Message msgObj = uiHandler.obtainMessage();
msgObj.what = MSG_SET_IMAGE_AND_PALETTE;
msgObj.obj = palette;
uiHandler.sendMessage(msgObj);
break;
case MSG_SET_IMAGE_AND_PALETTE:
Palette renderedPalette = (Palette) msg.obj;
setColors(renderedPalette);
break;
case MSG_SCROLL_UP_SCROLLVIEW:
int targetScroll = msg.arg1;
scrollView.smoothScrollTo(0, targetScroll);
break;
}
return false;
}
}