1

I am trying to make an Android View with a background like this:
enter image description here

I have figured out that the easiest way, properly is to make two shapes on top of each other with different background colors:

enter image description here

The height of the is different for each element, so I need to make the shape in code.
At first I have started in xml to quickly see the results. I have used the principles from this post to get started, but I don't really get close to anything usefull:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="45"
            android:toDegrees="45"
            android:pivotX="-60%"
            android:pivotY="50%" >
            <shape
                android:shape="rectangle">
                <solid
                    android:color="#FF00FF" />
            </shape>
        </rotate>
    </item>
</layer-list>


How should I do this?
Any clues of direction would be appriciated



I have done it in iOS like this but the shapes doesn't work the same way in Android:

self.view.backgroundColor = [self getEventColor];
CALayer *backgroundLayer = self.view.layer;

CAShapeLayer *mask = CAShapeLayer.new;
mask.frame = backgroundLayer.bounds;
mask.fillColor = [[UIColor blackColor] CGColor];

CGFloat width = backgroundLayer.frame.size.width;
CGFloat height = backgroundLayer.frame.size.height;

CGMutablePathRef path = CGPathCreateMutable();

int cornerCutSize = 20;
if (cornerCutSize > height)
    cornerCutSize = (int) height - 5;
CGPathMoveToPoint(path, NULL, 0, 0);
CGPathAddLineToPoint(path, nil, width, 0);
CGPathAddLineToPoint(path, nil, width, height - cornerCutSize);
CGPathAddLineToPoint(path, nil, width - cornerCutSize, height);
CGPathAddLineToPoint(path, nil, width, height);
CGPathAddLineToPoint(path, nil, 0, height);
CGPathAddLineToPoint(path, nil, 0, 0);
CGPathCloseSubpath(path);

mask.path = path;
CGPathRelease(path);

backgroundLayer.mask = mask;

UIColor *shadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.12];
self.topView.backgroundColor = shadowColor;

//add border
CAShapeLayer *border = [CAShapeLayer new];
border.frame = backgroundLayer.bounds;
border.path = path;
border.lineWidth = ProgramItemBorderSize;
border.strokeColor = shadowColor.CGColor;
border.fillColor = nil;
[backgroundLayer addSublayer:border];
Morten Holmgaard
  • 7,484
  • 8
  • 63
  • 85
  • 1
    It seems to me that you could easily create that background with a simple background XML of one color, then lay the lighter colored background in another XML in a relative layout inside. For the corner, just throw that shape in there as an image view and tuck it against the bottom and right. – durbnpoisn May 12 '14 at 20:25

2 Answers2

3

If all you have to deal with is varying height, make it a 9 patch drawable. Check out the developer guide : http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch http://developer.android.com/tools/help/draw9patch.html

If you want something closer to your iOS code, you could use a Path and draw to a canvas. For example, you could create a custom drawable to do this:

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.Drawable;

public class PathDrawable extends Drawable {

    Path mPath = new Path();
    Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public PathDrawable(){
        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setStrokeWidth(5);
    }

    @Override
    public void draw(Canvas canvas) {
        mPath.moveTo(10,10);
        mPath.lineTo(10, canvas.getHeight()-10);
        mPath.lineTo(canvas.getWidth()-50, canvas.getHeight()-10);
        mPath.lineTo(canvas.getWidth()-10, canvas.getHeight()-50);
        mPath.lineTo(canvas.getWidth()-10, 10);
        mPath.close();
        canvas.drawPath(mPath, mPaint);

    }

    @Override
    public void setAlpha(int i) {}

    @Override
    public void setColorFilter(ColorFilter colorFilter) {}

    @Override
    public int getOpacity() {
        return 0;
    }


}

Here I just draw one of the shapes, but you should get the idea.

Jens Zalzala
  • 2,546
  • 1
  • 22
  • 28
  • I need the solution with the drawPath to be able to customize it as much as I need. But the canvas.getHeight() and canvas.getWidth() returns the phones screen size - **How to get the size relative to the View the drawable is added to?** – Morten Holmgaard May 13 '14 at 16:41
  • I found a solution - I can pass it to the drawable from where it is created. Thanks - it works just fine. – Morten Holmgaard May 13 '14 at 16:54
  • 1
    Oh yea, drawable bounds always seem to be a black art for some reason. A lot of drawables support the setBounds() method. Since I override Drawable directly, that probably wasn't implemented. – Jens Zalzala May 13 '14 at 18:01
2

I agree with @durbnpoisn.

  1. Create a rectangle view with a background dark.
  2. Create a new rectangle view with a background light inside the first one. This one would have padding to give the effect of the border.
  3. Lay a triangle on the bottom right corner. The majority would be white except for a dark colored border along the overlapped side to finish the effect of a dark border around it.

I added an example of the layout. The yellow would be transparent.

Example of layout

Kalel Wade
  • 7,742
  • 3
  • 39
  • 55
  • 1
    The added bonus to this is that you could make that little triangle move with the height of the layout, thereby giving the illusion of it being auto-sizable. – durbnpoisn May 12 '14 at 20:34
  • @Kalel Wade, I suggest you provide a xml example to let people make use of it. – blueware Jun 21 '19 at 05:56