0

I'm trying to achieve a visual effect, that if I could make would look awesome! The login of the app that I'm doing looks like this:

enter image description here

Keep in mind that the image on the background is an animation, that makes a slightly transition from that image to another.

What I want is make the title of the app "Akrasia" be transparent, but transparent meaning that you can see the image in background through the title letters, this means that in some way I must override the onDraw method of the RelativeLayout that contains this form. I tried to do that, but the only thing that I got was errors. Maybe I'm wrong trying to override the onDraw method in boths, the TextView and the RelativeLayout, maybe there's an easiest way to do it. What do you think? Or maybe is impossible to achive this effect?

UPDATE:

This is how it should look like.

enter image description here

Also I tried to make a custom view extending from TextView wich has a method setBackgroundView wich stores a view instance into a field. Later on the onDraw method and I managed to get the bitmap from the background image. But I don't know how draw it using canvas.

UPDATE: I make it work! Now I only need change that blue-like background by the drawable of the background.

enter image description here

The view:

final public class SeeThroughTextView extends TextView
{
    Bitmap mMaskBitmap;
    Canvas mMaskCanvas;
    Paint mPaint;

    Drawable mBackground;
    Bitmap mBackgroundBitmap;
    Canvas mBackgroundCanvas;
    boolean mSetBoundsOnSizeAvailable = false;

    public SeeThroughTextView(Context context)
    {
        super(context);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    }

    public SeeThroughTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }



    @Override
    @Deprecated
    public void setBackgroundDrawable(Drawable bg)
    {
        mBackground = bg;
        int w = bg.getIntrinsicWidth();
        int h = bg.getIntrinsicHeight();

        // Drawable has no dimensions, retrieve View's dimensions
        if (w == -1 || h == -1)
        {
            w = getWidth();
            h = getHeight();
        }

        // Layout has not run
        if (w == 0 || h == 0)
        {
            mSetBoundsOnSizeAvailable = true;
            return;
        }

        mBackground.setBounds(0, 0, w, h);
        invalidate();
    }



    @Override
    public void setBackgroundColor(int color)
    {
        setBackgroundDrawable(new ColorDrawable(color));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mBackgroundCanvas = new Canvas(mBackgroundBitmap);
        mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mMaskCanvas = new Canvas(mMaskBitmap);

        if (mSetBoundsOnSizeAvailable)
        {
            mBackground.setBounds(0, 0, w, h);
            mSetBoundsOnSizeAvailable = false;
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        // Draw background
        mBackground.draw(mBackgroundCanvas);

        // Draw mask
        mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
        super.onDraw(mMaskCanvas);

        mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
        canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
    }
}

And in my fragment I have this because the animation in the background:

vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                vTitle.setBackgroundDrawable(new BitmapDrawable(vBackground.getDrawingCache()));
                vTitle.invalidate();
            }
        });
4gus71n
  • 3,717
  • 3
  • 39
  • 66

2 Answers2

2

Nailed!

enter image description here

The view:

final public class SeeThroughTextView extends TextView
{
    Bitmap mMaskBitmap;
    Canvas mMaskCanvas;
    Paint mPaint;

    Drawable mBackground;
    Bitmap mBackgroundBitmap;
    Canvas mBackgroundCanvas;
    boolean mSetBoundsOnSizeAvailable = false;

    public SeeThroughTextView(Context context)
    {
        super(context);
        init();
    }

    private void init() {
        Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/gillsans.ttf");
        setTypeface(myTypeface);
        mPaint = new Paint();
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    }

    public SeeThroughTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }



    @Override
    @Deprecated
    public void setBackgroundDrawable(Drawable bg)
    {
        mBackground = bg;
        int w = bg.getIntrinsicWidth();
        int h = bg.getIntrinsicHeight();

        // Drawable has no dimensions, retrieve View's dimensions
        if (w == -1 || h == -1)
        {
            w = getWidth();
            h = getHeight();
        }

        // Layout has not run
        if (w == 0 || h == 0)
        {
            mSetBoundsOnSizeAvailable = true;
            return;
        }

        mBackground.setBounds(0, 0, w, h);
        invalidate();
    }



    @Override
    public void setBackgroundColor(int color)
    {
        setBackgroundDrawable(new ColorDrawable(color));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mBackgroundCanvas = new Canvas(mBackgroundBitmap);
        mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mMaskCanvas = new Canvas(mMaskBitmap);

        if (mSetBoundsOnSizeAvailable)
        {
            mBackground.setBounds(0, 0, w, h);
            mSetBoundsOnSizeAvailable = false;
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        // Draw background
        mBackground.draw(mBackgroundCanvas);

        // Draw mask
        mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
        super.onDraw(mMaskCanvas);

        mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
        canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
    }
}

In my fragment:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    vLoginBtn = (Button) view.findViewById(R.id.btn_login);
    vRegistrationBtn = (Button) view.findViewById(R.id.btn_registration);
    vForgotBtn = (Button) view.findViewById(R.id.btn_forgot);
    vBackground = (KenBurnsView) view.findViewById(R.id.login_background);
    vTitle = (SeeThroughTextView) view.findViewById(R.id.txt_view_login_title);
    vBackground.setResourceUrls(
            "http://www.youwall.com/papel/peaceful_place_wallpaper_4f3f3.jpg",
            "http://www.fwallpaper.net/wallpapers/P/E/Peaceful-Scenary_1920x1200.jpg",
            "http://p1.pichost.me/i/39/1620902.jpg"
    );
    vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            vTitle.setBackgroundDrawable(getResources().getDrawable(R.drawable.drawable_background_login_top));
            vTitle.invalidate();
            vBackground.removeOnLayoutChangeListener(this);
        }
    });

}

The drawables are just two shapes, one with the top-left corner and top-right corner with radius 10dp and the another one with the radius in the bottoms. The custom TextView with the top drawable shape is alligned above the RelativeLayout wich contains the EditTexts. No much rocket science. Thanks a lot to @Klotor for suggesting the idea!

4gus71n
  • 3,717
  • 3
  • 39
  • 66
1

Specify a new color in your res/values/colors.xml file (create one if it doesn't exist), the file might look like:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="ltGray">#33999999</color>
</resources>

where the first two numbers are transparency (00 - fully transparent, FF - fully opaque).

Then simply set the text color of desired TextView to @color/ltGray in the xml of that layout, or go tvTitle.setTextColor(getResources().getColor(R.color.ltGray)) after instatiating the TextView.

Klotor
  • 181
  • 8
  • Sorry, maybe I didn't explain myself very well, see my update. – 4gus71n Apr 22 '15 at 13:11
  • I presume you want to set the text colour to #00000000 (fully transparent). – Mark Smith Apr 22 '15 at 13:21
  • Ah, okay. :) Sorry about that then. Try referring [here](http://stackoverflow.com/a/24281113/4796978), maybe this, or something similar, will work for you. I'd say `PorterDuffXferMode` is the way to go. If not then perhaps I'll try to help you out later on when I'm back home. :) – Klotor Apr 22 '15 at 13:33
  • Well, the link was really usefull, but I couldn't achive the effect right away. I'm still trying to modify that class to make it work, thanks for tip! – 4gus71n Apr 22 '15 at 14:20