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:
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.
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.
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();
}
});
Nailed!
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 EditText
s.
No much rocket science. Thanks a lot to @Klotor for suggesting the idea!