I'm working on an Android Project as a junior developer and am still learning as I go, I'm having a bit of a design issue and was wondering if somebody could enlighten me.
I have to display items on a horizontal list, I've done so with a RecyclerView, I can only have three items on screen at a time (one centered and two partially visible) and I'm always keeping one in the center thanks to a LinearSnapHelper. The problem I'm having is that the items on the side need to have a lower alpha than the one in the middle (0.5 vs 1). Ideally I would like to make them fade out and in progressively while the user I scrolling but I am completely at a loss as to where I am supposed to do this.
Horrible mockup here
Is there a clean way to do this ?
Thank you very much :)
If your RecyclerView
's background is a solid color, ie default Activity background color or white, a very simple approach would be to overlay the recycler with a semi transparent gradient drawable fading from a ~50% opacity bright color on the sides to a completely transparent one in the middle. This will give the illusion that the items are actually fading as you move them.
However creating complex gradients is not easy in drawable XML: you could just create an horizontal 3 colors gradient
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#55FFFFFF"
android:centerColor="#00FFFFFF"
android:endColor="#55FFFFFF"/>
</shape>
<!-- replace FFFFFF with the actual background color
and adjust the first two hexadecimal digits for the
overlay transparency (00 is transparent -> FF is opaque) -->
but probably this gradient will cover too much the center element and will be annoying.
In the central part the overlay has to be totally transparent, the gradient should start from outside the space occupied by the central view. This can be accomplished by overlaying two gradients:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:gravity="left"
android:right="200dp">
<shape android:shape="rectangle">
<gradient
android:type="linear"
android:startColor="#55FFFFFF"
android:endColor="#00FFFFFF"/>
</shape>
</item>
<item
android:left="200dp"
android:gravity="right">
<shape android:shape="rectangle">
<gradient
android:type="linear"
android:startColor="#55FFFFFF"
android:endColor="#AAFFFFFF"/>
</shape>
</item>
</layer-list>
Layer list is the only way to create multiple gradients in Android drawables. android:right="200dp"
and android:left="200dp"
are the distances between each gradient end and the opposite border of the view. In short if you replace 200dp with the space occupied by one side item + the central item, the space at the center will be left transparent as there will be no gradient on it.
Set one of these two gradients drawables in RecyclerView
's android:foreground=""
attribute in XML and see if it works.
The programmatic approach implies setting an OnScrollListener
in RecyclerView
or creating a custom LinearLayoutManager
which overrides scrollHorizontallyBy()
, something like this:
public void updateChildrenAlpha() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float maxDist = /* distance where alpha is min */;
float right = getDecoratedRight(child);
float left = getDecoratedLeft(child);
float childCenter = left + (right - left) / 2; // Get item center position
float center = getWidth() / 2; // Get RecyclerView's center position
child.setAlpha((Math.abs(center - childCenter) - maxDist) / maxDist);
// Map between 0f and 1f the abs value of the distance
// between the center of item and center of the RecyclerView
// and set it as alpha
}
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
updateChildrenAlpha();
return super.scrollHorizontallyBy(dx, recycler, state);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
updateChildrenAlpha();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With