/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package saulmm.avengers.views.activities; import android.animation.ValueAnimator; import android.content.Context; import android.content.Intent; import android.databinding.BindingAdapter; import android.databinding.DataBindingUtil; import android.graphics.Bitmap; import android.os.Bundle; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.graphics.Palette; import android.transition.Transition; import android.view.Gravity; import android.view.View; import android.view.ViewTreeObserver; import android.widget.ImageView; import butterknife.Bind; import butterknife.BindColor; import butterknife.BindInt; import butterknife.ButterKnife; import com.bumptech.glide.Glide; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.BitmapImageViewTarget; import javax.inject.Inject; import saulmm.avengers.AvengersApplication; import saulmm.avengers.R; import saulmm.avengers.databinding.ActivityAvengerDetailBinding; import saulmm.avengers.entities.CollectionItem; import saulmm.avengers.entities.MarvelCharacter; import saulmm.avengers.injector.components.DaggerAvengerInformationComponent; import saulmm.avengers.injector.modules.ActivityModule; import saulmm.avengers.injector.modules.AvengerInformationModule; import saulmm.avengers.mvp.presenters.CharacterDetailPresenter; import saulmm.avengers.mvp.views.CharacterDetailView; import saulmm.avengers.utils.OnCharacterImageCallback; import saulmm.avengers.utils.TransitionUtils; import saulmm.avengers.views.utils.AnimUtils; public class CharacterDetailActivity extends AppCompatActivity implements CharacterDetailView { private static final String EXTRA_CHARACTER_NAME = "character.name"; public static final String EXTRA_CHARACTER_ID = "character.id"; @Bind(R.id.character_collapsing) CollapsingToolbarLayout mCollapsing; @BindInt(R.integer.duration_medium) int mAnimMediumDuration; @BindInt(R.integer.duration_huge) int mAnimHugeDuration; @BindColor(R.color.brand_primary_dark) int mColorPrimaryDark; @Inject CharacterDetailPresenter mCharacterDetailPresenter; private ActivityAvengerDetailBinding mBinding; private OnCharacterImageCallback onCharacterImageCallback = new OnCharacterImageCallback() { @Override public void onReceive(Bitmap bitmap) { initActivityColors(bitmap); } }; private int mScrolleableAppbarLayoutFlags; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initializeDependencyInjector(); initializeBinding(); initButterknife(); initializePresenter(); initToolbar(); initTransitions(); } @Override public void disableScroll() { mScrolleableAppbarLayoutFlags = ((AppBarLayout.LayoutParams) mCollapsing.getLayoutParams()).getScrollFlags(); AppBarLayout.LayoutParams layoutParams = ((AppBarLayout.LayoutParams) mCollapsing.getLayoutParams()); layoutParams.setScrollFlags(0); mCollapsing.setLayoutParams(layoutParams); } private void initializeBinding() { mBinding = DataBindingUtil.setContentView( this, R.layout.activity_avenger_detail); mBinding.setImageCallback(onCharacterImageCallback); } public void initActivityColors(Bitmap sourceBitmap) { Palette.from(sourceBitmap) .generate(palette -> { View statsRevealView = mBinding.characterStatsReveal; View imageCover = mBinding.characterImageReveal; int darkVibrant = palette.getDarkVibrantColor(mColorPrimaryDark); mBinding.setDarkSwatch(palette.getDarkVibrantSwatch()); ValueAnimator colorAnimation = ValueAnimator.ofArgb(mColorPrimaryDark, darkVibrant); colorAnimation.setDuration(mAnimHugeDuration); colorAnimation.addUpdateListener(animator -> { imageCover.setBackgroundColor((Integer) animator.getAnimatedValue()); }); colorAnimation.start(); statsRevealView.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { statsRevealView.getViewTreeObserver() .removeOnGlobalLayoutListener(this); AnimUtils.showRevealEffect(statsRevealView, statsRevealView.getWidth() / 2, 0, null); } }); getWindow().setStatusBarColor(darkVibrant); }); } private void initButterknife() { ButterKnife.bind(this); } @Override protected void onStart() { super.onStart(); mCharacterDetailPresenter.onStart(); } private void initializePresenter() { int characterId = getIntent().getIntExtra(EXTRA_CHARACTER_ID, -1); String characterName = getIntent().getStringExtra(EXTRA_CHARACTER_NAME); mCharacterDetailPresenter.attachView(this); mCharacterDetailPresenter.setCharacterId(characterId); mCharacterDetailPresenter.initializePresenter(characterId, characterName); mCharacterDetailPresenter.onCreate(); mBinding.setPresenter(mCharacterDetailPresenter); } private void initializeDependencyInjector() { AvengersApplication avengersApplication = (AvengersApplication) getApplication(); int avengerId = getIntent().getIntExtra(EXTRA_CHARACTER_ID, -1); DaggerAvengerInformationComponent.builder() .activityModule(new ActivityModule(this)) .appComponent(avengersApplication.getAppComponent()) .avengerInformationModule(new AvengerInformationModule(avengerId)) .build().inject(this); } private void initTransitions() { final String sharedViewName = getIntent().getStringExtra( CharacterListActivity.EXTRA_IMAGE_TRANSITION_NAME); String characterTitle = getIntent().getStringExtra( CharacterListActivity.EXTRA_CHARACTER_NAME); Transition enterTransition = TransitionUtils.buildSlideTransition(Gravity.BOTTOM); enterTransition.setDuration(mAnimMediumDuration); getWindow().setEnterTransition(enterTransition); getWindow().setReturnTransition(TransitionUtils.buildSlideTransition(Gravity.BOTTOM)); View collapsingToolbar = mBinding.characterCollapsing; View imageReveal = mBinding.characterImageReveal; collapsingToolbar.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { collapsingToolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width = imageReveal.getWidth(); int height = imageReveal.getHeight(); AnimUtils.showRevealEffect(imageReveal, width / 2, height / 2, null); } }); } @Override public void hideRevealViewByAlpha() { mBinding.characterImageReveal.animate().alpha(0f).setDuration( mAnimHugeDuration).start(); } private void initToolbar() { mBinding.characterToolbar.setNavigationOnClickListener(v -> onBackPressed()); } @Override public void showError(String errorMessage) { new AlertDialog.Builder(this) .setTitle(getString(R.string.dialog_error)) .setPositiveButton(getString(R.string.action_accept), (dialog, which) -> finish()) .setMessage(errorMessage) .setCancelable(false).show(); } @Override public void bindCharacter(MarvelCharacter character) { mBinding.setCharacter(character); } @Override public void enableScroll() { AppBarLayout.LayoutParams layoutParams = (AppBarLayout.LayoutParams) mCollapsing.getLayoutParams(); layoutParams.setScrollFlags(mScrolleableAppbarLayoutFlags); mCollapsing.setLayoutParams(layoutParams); } @Override public void goToCharacterComicsView(int characterId) { CollectionActivity.start(this, characterId, CollectionItem.COMICS); } @Override public void goToCharacterSeriesView(int characterId) { CollectionActivity.start(this, characterId, CollectionItem.SERIES); } @Override public void goToCharacterEventsView(int characterId) { CollectionActivity.start(this, characterId, CollectionItem.EVENTS); } @Override public void goToCharacterStoriesView(int characterId) { CollectionActivity.start(this, characterId, CollectionItem.STORIES); } @BindingAdapter({"source", "presenter", "callback"}) public static void setImageSource(ImageView v, String url, CharacterDetailPresenter detailPresenter, OnCharacterImageCallback imageCallback) { Glide.with(v.getContext()).load(url).asBitmap().into(new BitmapImageViewTarget(v) { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { super.onResourceReady(resource, glideAnimation); v.setImageBitmap(resource); imageCallback.onReceive(resource); detailPresenter.onImageReceived(); } }); } @Override protected void onStop() { super.onStop(); mCharacterDetailPresenter.onStop(); } public static void start(Context context, String characterName, int characterId) { Intent characterDetailItent = new Intent(context, CharacterDetailActivity.class); characterDetailItent.putExtra(EXTRA_CHARACTER_NAME, characterName); characterDetailItent.putExtra(EXTRA_CHARACTER_ID, characterId); context.startActivity(characterDetailItent); } }