Is there any way to apply vertical/horizontal fading edges to an ImageView
component?
I already tried android:fadingEdge
but unfortunately this attribute is deprecated and will be ignored as of API level 14, Any ideas?
I have found a neat workaround that worked perfectly for me. I needed to fade out the top and the bottom of the imageView (this approach works for any side though, simply create a different gradient). I wrapped the ImageView
inside of a FrameLayout
and put 2 View
s to the top and bottom, after that, I created the xml's with gradients for the background of these and simply put them as backgrounds. Here's how it looks:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/fade_effect_heigth"
android:layout_gravity="bottom"
android:background="@drawable/custom_gradient_bottom"/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/fade_effect_heigth"
android:layout_gravity="top"
android:background="@drawable/custom_gradient_top"/>
</FrameLayout>
Now the 2 Views are on top of the image view, and their gradient xml background files look like this (this is the top gradient, bottom is the same just flip the start/end color):
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:angle="90"
android:startColor="#00000000" <- black with 0 alpha, so transparent
android:endColor="#000000" <- black color
android:type="linear" />
You can choose the height of the fade that works for you, I chose 120dp and it served my needs well. Here's a screenshot from my emulator of the ImageView
only:
I create the following extend of ImageView
to incorporate it with horizontal fading, you can easily change this class and add vertical fading. (Tested with the latest android version 4.4.2)
Base class:
public class FadingImageView extends ImageView {
private FadeSide mFadeSide;
private Context c;
public enum FadeSide {
RIGHT_SIDE, LEFT_SIDE
}
public FadingImageView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
this.c = c;
init();
}
public FadingImageView(Context c, AttributeSet attrs) {
super(c, attrs);
this.c = c;
init();
}
public FadingImageView(Context c) {
super(c);
this.c = c;
init();
}
private void init() {
// Enable horizontal fading
this.setHorizontalFadingEdgeEnabled(true);
// Apply default fading length
this.setEdgeLength(14);
// Apply default side
this.setFadeDirection(FadeSide.RIGHT_SIDE);
}
public void setFadeDirection(FadeSide side) {
this.mFadeSide = side;
}
public void setEdgeLength(int length) {
this.setFadingEdgeLength(getPixels(length));
}
@Override
protected float getLeftFadingEdgeStrength() {
return mFadeSide.equals(FadeSide.LEFT_SIDE) ? 1.0f : 0.0f;
}
@Override
protected float getRightFadingEdgeStrength() {
return mFadeSide.equals(FadeSide.RIGHT_SIDE) ? 1.0f : 0.0f;
}
@Override
public boolean hasOverlappingRendering() {
return true;
}
@Override
public boolean onSetAlpha(int alpha) {
return false;
}
private int getPixels(int dipValue) {
Resources r = c.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dipValue, r.getDisplayMetrics());
}
}
Usage:
- Create the following object in your XML:
<com.your.package.FadingImageView
android:id="@+id/fade_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/some_drawable" />
- Then apply your desired fade side:
FadingImageView mFadingImageView = (FadingImageView) findViewById(R.id.fade_image_view);
mFadingImageView.setEdgeLength(28);
mFadingImageView.setFadeDirection(FadeSide.RIGHT_SIDE);
A small addition to Vucko's answer.
This class can add fade to multiple edges at once.
public class FadingImageView extends AppCompatImageView {
private boolean mFadeRight;
private boolean mFadeLeft;
private boolean mFadeTop;
private boolean mFadeBottom;
private Context c;
public FadingImageView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
this.c = c;
init();
}
public FadingImageView(Context c, AttributeSet attrs) {
super(c, attrs);
this.c = c;
init();
}
public FadingImageView(Context c) {
super(c);
this.c = c;
init();
}
private void init() {
// Enable horizontal fading
this.setHorizontalFadingEdgeEnabled(true);
this.setVerticalFadingEdgeEnabled(true);
// Apply default fading length
this.setEdgeLength(14);
// Apply default side
this.setFadeRight(true);
}
public void setFadeRight(boolean fadeRight) {
mFadeRight = fadeRight;
}
public void setFadeLeft(boolean fadeLeft) {
mFadeLeft = fadeLeft;
}
public void setFadeTop(boolean fadeTop) {
mFadeTop = fadeTop;
}
public void setFadeBottom(boolean fadeBottom) {
mFadeBottom = fadeBottom;
}
public void setEdgeLength(int length) {
this.setFadingEdgeLength(getPixels(length));
}
@Override
protected float getTopFadingEdgeStrength() {
return mFadeTop ? 1.0f : 0.0f;
}
@Override
protected float getBottomFadingEdgeStrength() {
return mFadeBottom ? 1.0f : 0.0f;
}
@Override
protected float getLeftFadingEdgeStrength() {
return mFadeLeft ? 1.0f : 0.0f;
}
@Override
protected float getRightFadingEdgeStrength() {
return mFadeRight ? 1.0f : 0.0f;
}
@Override
public boolean hasOverlappingRendering() {
return true;
}
@Override
public boolean onSetAlpha(int alpha) {
return false;
}
private int getPixels(int dipValue) {
Resources r = c.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dipValue, r.getDisplayMetrics());
}
}
And to add fade to all edges
mFadingImageView.setFadeTop(true);
mFadingImageView.setFadeBottom(true);
mFadingImageView.setFadeLeft(true);
mFadingImageView.setFadeRight(true);
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