package com.pierfrancescosoffritti.shrinkingimagelayout; import android.animation.AnimatorInflater; import android.animation.StateListAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.os.Build; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.pierfrancescosoffritti.shrinkingimagelayout.parallaxScrimageView.ParallaxScrimageView; public class ShrinkingImageLayout extends FrameLayout { private ParallaxScrimageView parallaxScrimageView; private RecyclerView recyclerView; private LinearLayoutManager layoutManager; private HeaderRecyclerViewAdapter adapter; private LinearLayout header; private int imageMaximumHeight; private int imageMinimumHeight; private RecyclerView.OnScrollListener onScollListener; public ShrinkingImageLayout(Context context) { this(context, null, 0); } public ShrinkingImageLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ShrinkingImageLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); imageMaximumHeight = (int) (getResources().getDimensionPixelSize(R.dimen._168dp)*1.5); imageMinimumHeight = getResources().getDimensionPixelSize(R.dimen._168dp); initParallaxScrimView(); initHeader(); } public void setImageMaximumHeight(int maximumHeight) { imageMaximumHeight = maximumHeight; View space = header.findViewById(R.id.space); ViewGroup.LayoutParams spaceParams = space.getLayoutParams(); spaceParams.height = maximumHeight; space.setLayoutParams(spaceParams); ViewGroup.LayoutParams parallaxParams = parallaxScrimageView.getLayoutParams(); parallaxParams.height = maximumHeight; parallaxScrimageView.setLayoutParams(parallaxParams); } public void setImageMinimumHeight(int minimumHeight) { this.imageMinimumHeight = minimumHeight; parallaxScrimageView.setMinimumHeight(minimumHeight); } private void initHeader() { header = new LinearLayout(getContext()); header.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); header.setOrientation(LinearLayout.VERTICAL); View space = new View(getContext()); space.setId(R.id.space); space.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, imageMaximumHeight)); header.addView(space); } private void initParallaxScrimView() { parallaxScrimageView = new ParallaxScrimageView(getContext()); parallaxScrimageView.setId(R.id.parallaxImageView); parallaxScrimageView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, imageMaximumHeight)); parallaxScrimageView.setMinimumHeight(imageMinimumHeight); int[] attrs = new int[] { R.attr.selectableItemBackground }; TypedArray ta = getContext().obtainStyledAttributes(attrs); Drawable selectableItemBackground = ta.getDrawable(0); ta.recycle(); parallaxScrimageView.setClickable(true); parallaxScrimageView.setForeground(selectableItemBackground); parallaxScrimageView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.light_grey)); parallaxScrimageView.setScrimColor(ContextCompat.getColor(getContext(), R.color.scrim)); parallaxScrimageView.setScrimAlpha(0f); parallaxScrimageView.setMaxSrimAlpha(0.4f); parallaxScrimageView.setParallaxFactor(-0.5f); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { StateListAnimator stateListAnimator = AnimatorInflater.loadStateListAnimator(getContext(), R.animator.app_bar_pin); parallaxScrimageView.setStateListAnimator(stateListAnimator); } } public void addCustomHeader(@NonNull View header) { this.header.addView(header, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } public void setupRecyclerView(@NonNull RecyclerView recyclerView, @NonNull LinearLayoutManager layoutManager, @NonNull HeaderRecyclerViewAdapter adapter) { this.recyclerView = recyclerView; this.adapter = adapter; this.layoutManager = layoutManager; adapter.setHeader(this.header); initScrollListener(); initRecyclerView(); } private void initScrollListener() { onScollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition(); if (firstVisibleItemPosition == 0 && recyclerView.getChildAt(0) != null) { final int listScroll = recyclerView.getChildAt(0).getTop(); parallaxScrimageView.setOffset(listScroll); } } }; } private void initRecyclerView() { if(recyclerView.getParent() != null && recyclerView.getParent() != this) throw new IllegalArgumentException("recyclerView parent must be ShrinkingImageLayout or none"); this.recyclerView.setLayoutManager(layoutManager); this.recyclerView.setAdapter(adapter); this.recyclerView.addOnScrollListener(onScollListener); if(recyclerView.getParent() == null) this.addView(recyclerView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); if(parallaxScrimageView.getParent() == null) this.addView(parallaxScrimageView); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if(this.recyclerView == null) throw new IllegalStateException("recyclerView == null. You must call 'addRecyclerView'."); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public void setImageResource(@DrawableRes int id) { parallaxScrimageView.setImageResource(id); } public void setImageDrawable(Drawable drawable) { parallaxScrimageView.setImageDrawable(drawable); } public void setImageBitmap(Bitmap image) { parallaxScrimageView.setImageBitmap(image); } public ImageView getImageView() { return parallaxScrimageView; } }