× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Creating animation for images from small to large when scrolling vertical

Xaver Kapeller
Mar 13, 2015
<p>I have created a basic custom view which replicates this behaviour, it's not completely the same but I think it's close enough for now, if it needs to be exactly the same this can be quickly achieved by modifying the <code>updateChildViews()</code> method. I wrote this class in 20 minutes so it's far from perfect, for a production ready solution some additional work has to be done. Generally this solution works with all kinds of child views, but to replicate the exact behaviour use an ImageView as background for your child views and set this property on the ImageViews:</p> <pre><code>android:scaleType="centerCrop" </code></pre> <p>Problems I see with my solution in it's current state:</p> <ul> <li>Only works in vertical orientation</li> <li>No view recycling. </li> <li>Should be derived from AdapterView and not LinearLayout.</li> </ul> <p>Anyway that's how it looks so far:</p> <p><img src="http://i.stack.imgur.com/4Tj0V.gif" alt="enter image description here"></p> <p>Here is the source code:</p> <pre><code>import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; public class Accordion extends LinearLayout { private static final String LOG_TAG = Accordion.class.getSimpleName(); private double scrollProgress = 0.0; private double topViewScaleFactor = 2.0; private double collapsedViewHeight = 200.0; private double expandedViewHeight = 700.0; private double scrollProgressPerView = expandedViewHeight; private final ScrollTouchListener touchListener = new ScrollTouchListener() { @Override protected void onScroll(float x, float y) { scrollProgress += y; if(scrollProgress &lt; 0.0) { scrollProgress = 0.0; } int viewCount = getChildCount(); double maxScrollProgress = (viewCount - 1) * scrollProgressPerView + 1; if(scrollProgress &gt; maxScrollProgress) { scrollProgress = maxScrollProgress; } Log.i(LOG_TAG, String.format("Scroll Progress: %f", scrollProgress)); updateChildViews(); } }; public Accordion(Context context) { super(context); this.setOnTouchListener(this.touchListener); } public Accordion(Context context, AttributeSet attrs) { super(context, attrs); this.setOnTouchListener(this.touchListener); } public Accordion(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setOnTouchListener(this.touchListener); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); updateChildViews(); } private void updateChildViews() { int viewCount = getChildCount(); double progress = scrollProgress; double overflow = 0; for(int i = 0; i &lt; viewCount; i++) { View child = getChildAt(i); if(child != null) { if(progress &gt;= scrollProgressPerView) { progress -= scrollProgressPerView; child.setVisibility(View.GONE); setChildHeight(child, 0); } else if (progress &gt; 0) { setChildHeight(child, expandedViewHeight - progress); overflow = progress; child.setVisibility(View.VISIBLE); progress = 0; } else { if(overflow &gt; 0) { double height = collapsedViewHeight + overflow; if(height &gt; expandedViewHeight) { height = expandedViewHeight; } setChildHeight(child, height); overflow = 0; } else { setChildHeight(child, i &gt; 0 ? collapsedViewHeight : expandedViewHeight); } child.setVisibility(View.VISIBLE); } } } } private void setChildHeight(View child, double height) { child.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)height)); } private static abstract class ScrollTouchListener implements OnTouchListener { private static final String LOG_TAG = ScrollTouchListener.class.getSimpleName(); private boolean scrolling = false; private float x = 0; private float y = 0; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: x = event.getX(); y = event.getY(); scrolling = true; return true; case MotionEvent.ACTION_UP: scrolling = false; return true; case MotionEvent.ACTION_MOVE: if (scrolling) { float newX = event.getX(); float newY = event.getY(); float difX = x - newX; float difY = y - newY; onScroll(difX, difY); x = newX; y = newY; } return true; default: return false; } } protected abstract void onScroll(float x, float y); } } </code></pre> <p>To use it just put it in a layout like this:</p> <pre><code>&lt;at.test.app.Accordion xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"&gt; &lt;ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/alpen"/&gt; &lt;ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/alpen"/&gt; &lt;ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/alpen"/&gt; &lt;ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/alpen"/&gt; &lt;/at.test.app.Accordion&gt; </code></pre> <p>If you have any additional questions feel free to ask!</p> <p>This tip was originally posted on <a href="http://stackoverflow.com/questions/22472060/Creating%20animation%20for%20images%20from%20small%20to%20large%20when%20scrolling%20vertical/22476800">Stack Overflow</a>.</p>

Get New Tutorials Delivered to Your Inbox

New tutorials will be sent to your Inbox once a week.

comments powered by Disqus