package com.looklook.xinghongfei.looklook.activity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.graphics.Bitmap; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; import android.support.v4.widget.NestedScrollView; import android.support.v7.app.AppCompatActivity; import android.support.v7.graphics.Palette; import android.support.v7.widget.Toolbar; import android.transition.Transition; import android.util.TypedValue; import android.view.View; import android.view.ViewTreeObserver; import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.ProgressBar; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.Target; import com.looklook.xinghongfei.looklook.R; import com.looklook.xinghongfei.looklook.bean.news.NewsDetailBean; import com.looklook.xinghongfei.looklook.presenter.implPresenter.TopNewsDesPresenterImpl; import com.looklook.xinghongfei.looklook.presenter.implView.ITopNewsDesFragment; import com.looklook.xinghongfei.looklook.util.AnimUtils; import com.looklook.xinghongfei.looklook.util.ColorUtils; import com.looklook.xinghongfei.looklook.util.DensityUtil; import com.looklook.xinghongfei.looklook.util.GlideUtils; import com.looklook.xinghongfei.looklook.util.ViewUtils; import com.looklook.xinghongfei.looklook.widget.ElasticDragDismissFrameLayout; import com.looklook.xinghongfei.looklook.widget.ParallaxScrimageView; import com.looklook.xinghongfei.looklook.widget.TranslateYTextView; import org.sufficientlysecure.htmltextview.HtmlTextView; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; /** * Created by xinghongfei on 16/8/13. */ public class TopNewsDescribeActivity extends AppCompatActivity implements ITopNewsDesFragment { private static final float SCRIM_ADJUSTMENT = 0.075f; int[] mDeviceInfo; int width; int heigh; @BindView(R.id.progress) ProgressBar mProgress; @BindView(R.id.htNewsContent) HtmlTextView mHtNewsContent; @BindView(R.id.shot) ParallaxScrimageView mShot; @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.draggable_frame) ElasticDragDismissFrameLayout mDraggableFrame; @BindView(R.id.nest) NestedScrollView mNest; @BindView(R.id.title) TranslateYTextView mTextView; private String id; private String title; private String mImageUrl; private ElasticDragDismissFrameLayout.SystemChromeFader chromeFader; private TopNewsDesPresenterImpl mTopNewsDesPresenter; private NestedScrollView.OnScrollChangeListener scrollListener; private Transition.TransitionListener mReturnHomeListener; private Transition.TransitionListener mEnterTrasitionListener; private RequestListener glideLoadListener = new RequestListener<String, GlideDrawable>() { @Override public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { final Bitmap bitmap = GlideUtils.getBitmap(resource); final int twentyFourDip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, TopNewsDescribeActivity.this.getResources().getDisplayMetrics()); Palette.from(bitmap) .maximumColorCount(3) .clearFilters() /* by default palette ignore certain hues (e.g. pure black/white) but we don't want this. */ .setRegion(0, 0, bitmap.getWidth() - 1, twentyFourDip) /* - 1 to work around https://code.google.com/p/android/issues/detail?id=191013 */ .generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { boolean isDark; @ColorUtils.Lightness int lightness = ColorUtils.isDark(palette); if (lightness == ColorUtils.LIGHTNESS_UNKNOWN) { isDark = ColorUtils.isDark(bitmap, bitmap.getWidth() / 2, 0); } else { isDark = lightness == ColorUtils.IS_DARK; } // color the status bar. Set a complementary dark color on L, // light or dark color on M (with matching status bar icons) int statusBarColor = getWindow().getStatusBarColor(); final Palette.Swatch topColor = ColorUtils.getMostPopulousSwatch(palette); if (topColor != null && (isDark || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)) { statusBarColor = ColorUtils.scrimify(topColor.getRgb(), isDark, SCRIM_ADJUSTMENT); // set a light status bar on M+ if (!isDark && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ViewUtils.setLightStatusBar(mShot); } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (statusBarColor != getWindow().getStatusBarColor()) { mShot.setScrimColor(statusBarColor); ValueAnimator statusBarColorAnim = ValueAnimator.ofArgb( getWindow().getStatusBarColor(), statusBarColor); statusBarColorAnim.addUpdateListener(new ValueAnimator .AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { getWindow().setStatusBarColor( (int) animation.getAnimatedValue()); } }); statusBarColorAnim.setDuration(1000L); statusBarColorAnim.setInterpolator( new AccelerateInterpolator()); statusBarColorAnim.start(); } } } }); Palette.from(bitmap) .clearFilters() .generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { // slightly more opaque ripple on the pinned image to compensate // for the scrim if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mShot.setForeground(ViewUtils.createRipple(palette, 0.3f, 0.6f, ContextCompat.getColor(TopNewsDescribeActivity.this, R.color.mid_grey), true)); } } }); // TODO should keep the background if the image contains transparency?! mShot.setBackground(null); return false; } @Override public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { return false; } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.topnews_describe); ButterKnife.bind(this); setSupportActionBar(mToolbar); mDeviceInfo = DensityUtil.getDeviceInfo(this); width = mDeviceInfo[0]; heigh = width * 3 / 4; initData(); initView(); getData(); enterAnimation(); chromeFader = new ElasticDragDismissFrameLayout.SystemChromeFader(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getSharedElementReturnTransition().addListener(mReturnHomeListener); getWindow().getSharedElementEnterTransition().addListener(mEnterTrasitionListener); } } protected void initData() { id = getIntent().getStringExtra("docid"); title = getIntent().getStringExtra("title"); mTextView.setText(title); mImageUrl = getIntent().getStringExtra("image"); scrollListener = new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { if (oldScrollY < 168) { mShot.setOffset(-oldScrollY); mTextView.setOffset(-oldScrollY); } } }; Glide.with(this) .load(mImageUrl) .override(width, heigh) .listener(glideLoadListener) .centerCrop() .diskCacheStrategy(DiskCacheStrategy.SOURCE) .into(mShot); mTopNewsDesPresenter = new TopNewsDesPresenterImpl(this); mNest.setOnScrollChangeListener(scrollListener); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { postponeEnterTransition(); mShot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { mShot.getViewTreeObserver().removeOnPreDrawListener(this); startPostponedEnterTransition(); return true; } }); } mReturnHomeListener = new AnimUtils.TransitionListenerAdapter() { @Override public void onTransitionStart(Transition transition) { super.onTransitionStart(transition); // hide the fab as for some reason it jumps position?? TODO work out why mToolbar.animate() .alpha(0f) .setDuration(100) .setInterpolator(new AccelerateInterpolator()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mShot.setElevation(1f); mToolbar.setElevation(0f); } mNest.animate() .alpha(0f) .setDuration(50) .setInterpolator(new AccelerateInterpolator()); } }; mEnterTrasitionListener = new AnimUtils.TransitionListenerAdapter() { @Override public void onTransitionEnd(Transition transition) { super.onTransitionEnd(transition); // 解决5.0 shara element bug ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100).setDuration(100); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // mShot.setOffset((Integer) valueAnimator.getAnimatedValue() * 10); mNest.smoothScrollTo((Integer) valueAnimator.getAnimatedValue() / 10, 0); } }); valueAnimator.start(); // mShot.setAlpha(0.5f); // mShot.animate().alpha(1f).setDuration(800L).start(); } @Override public void onTransitionResume(Transition transition) { super.onTransitionResume(transition); } }; } private void initView() { mNest.setAlpha(0.5f); mToolbar.setNavigationIcon(R.drawable.ic_arrow_back); mToolbar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mNest.smoothScrollTo(0, 0); } }); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { expandImageAndFinish(); } }); } @Override protected void onResume() { super.onResume(); mDraggableFrame.addListener(chromeFader); } @Override protected void onPause() { super.onPause(); mDraggableFrame.removeListener(chromeFader); } @Override protected void onDestroy() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getSharedElementReturnTransition().removeListener(mReturnHomeListener); getWindow().getSharedElementEnterTransition().removeListener(mEnterTrasitionListener); } mTopNewsDesPresenter.unsubscrible(); super.onDestroy(); } @Override public void onBackPressed() { super.onBackPressed(); expandImageAndFinish(); } private void getData() { mTopNewsDesPresenter.getDescribleMessage(id); } @OnClick(R.id.shot) public void onClick() { mNest.smoothScrollTo(0, 0); } @Override public void showProgressDialog() { mProgress.setVisibility(View.VISIBLE); } @Override public void hidProgressDialog() { mProgress.setVisibility(View.INVISIBLE); } @Override public void showError(String error) { Snackbar.make(mDraggableFrame, getString(R.string.snack_infor), Snackbar.LENGTH_INDEFINITE).setAction("重试", new View.OnClickListener() { @Override public void onClick(View v) { getData(); } }).show(); } private void expandImageAndFinish() { if (mShot.getOffset() != 0f) { Animator expandImage = ObjectAnimator.ofFloat(mShot, ParallaxScrimageView.OFFSET, 0f); expandImage.setDuration(80); expandImage.setInterpolator(new AccelerateInterpolator()); expandImage.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAfterTransition(); } else { finish(); } } }); expandImage.start(); } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAfterTransition(); } else { finish(); } } } private void enterAnimation() { float offSet = mToolbar.getHeight(); LinearInterpolator interpolator = new LinearInterpolator(); AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator(); viewEnterAnimation(mToolbar, offSet, interpolator); viewEnterAnimationNest(mNest, 0f, accelerateInterpolator); } private void viewEnterAnimation(View view, float offset, Interpolator interp) { view.setTranslationY(-offset); view.setAlpha(0.6f); view.animate() .translationY(0f) .alpha(1f) .setDuration(600L) .setInterpolator(interp) .setListener(null) .start(); } private void viewEnterAnimationNest(View view, float offset, Interpolator interp) { view.setTranslationY(-offset); view.animate() .translationY(0f) .alpha(1f) .setDuration(50L) .setInterpolator(interp) .setListener(null) .start(); } @Override public void updateListItem(NewsDetailBean newsList) { mProgress.setVisibility(View.INVISIBLE); mHtNewsContent.setHtmlFromString(newsList.getBody(), new HtmlTextView.LocalImageGetter()); } }