I am trying to create a drawable, where I have 3 circles (on top of each other) on a linear gradient and the circles are shifted 50% to the left.
This is my attempt so far:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient
android:startColor="#4833A6"
android:endColor="#1E479C"
android:type="linear"
/>
</shape>
</item>
<item android:left="-115dp">
<shape android:shape="oval">
<size android:width="230dp" android:height="233dp"/>
<solid android:color="#1AFFFFFF"/>
</shape>
</item>
<item android:left="-83dp">
<shape android:shape="oval">
<size android:width="166dp" android:height="166dp"/>
<solid android:color="#1AFFFFFF"/>
</shape>
</item>
<item android:left="-57.5dp">
<shape android:shape="oval">
<size android:width="115dp" android:height="115dp"/>
<solid android:color="#1AFFFFFF"/>
</shape>
</item>
</layer-list>
The desired effect:
What I have so far :(
What am I doing wrong?
Try to put in your item, the following:
<item
android:width="115dp"
android:height="115dp"
android:gravity="center|left"
android:left="-57dp">
<shape android:shape="oval">
<solid android:color="#1AFFFFFF"/>
</shape>
</item>
Don't define the size inside the shape, but inside the item itself. I tried here, and it's working properly.
what is purpose of stroke here :
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/rippleEffectColor"
xmlns:tools="ht-- tp://schemas.android.com/tools"
tools:targetApi="lollipop">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/signin"></solid>
<corners android:radius="4dp"></corners>
<stroke android:color="#color/yellow"></stroke>
</shape>
</item>
because the ripple effect is done by the android:colour="#colour/rippleEffectColor"
I have the following layout:
<LinearLayout
android:id="#+id/myButton"
android:layout_width="#dimen/logo_radius"
android:layout_height="match_parent"
android:background="#drawable/myShape">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/driver_half"/>
</LinearLayout>
and the following myShape drawable:
<selector>
<item><shape android:shape="oval">
<stroke android:color="#android:color/black" android:width="4dp"/>
<solid android:color="#android:color/white" />
</shape></item>
</selector>
I applied the following filter:
myButton.getBackground().setColorFilter( orange, PorterDuff.Mode.ADD );
the result looked that way:
Then I changed myShape to be a rectangle with rounded corners:
<selector>
<item>
<shape
android:shape="rectangle">
<corners android:bottomLeftRadius="#dimen/logo_radius" android:bottomRightRadius="2dp" android:topLeftRadius="#dimen/logo_radius" android:topRightRadius="2dp"/>
<stroke
android:width="4dp"
android:color="#android:color/black"/>
<solid android:color="#android:color/white"/>
</shape>
</item>
</selector>
the result looked like:
left part is without the filter applied, the right part with the filter.
what I want to get:
What should I do to properly paint the border orange using the Porter-Duff filter? Are there any other options?
Porter/Duff filtering depends on image alpha channel. To paint shapes border only (without other shape space) you should change shape background from white to transparent:
<selector>
<item>
<shape
android:shape="rectangle">
<corners android:bottomLeftRadius="#dimen/logo_radius" android:bottomRightRadius="2dp" android:topLeftRadius="#dimen/logo_radius" android:topRightRadius="2dp"/>
<stroke
android:width="4dp"
android:color="#android:color/black"/>
<solid android:color="#android:color/transparent"/>
</shape>
</item>
</selector>
and correct PorterDuff.Mode for this case should be SRC_IN.
But I don't know why oval-shape painted correctly.
UPD:
with SRC_IN the border is painted orange, but the filling remains transparent...
You can change your selector to layer-list drawable like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/background">
<shape android:shape="rectangle">
<corners
android:bottomLeftRadius="32dp"
android:bottomRightRadius="2dp"
android:topLeftRadius="32dp"
android:topRightRadius="2dp" />
<solid android:color="#android:color/white" />
</shape>
</item>
<item android:id="#+id/border">
<shape android:shape="rectangle">
<corners
android:bottomLeftRadius="32dp"
android:bottomRightRadius="2dp"
android:topLeftRadius="32dp"
android:topRightRadius="2dp" />
<stroke
android:width="4dp"
android:color="#android:color/black" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
</layer-list>
and set color filter only for border item:
LayerDrawable background = LayerDrawable.class.cast(findViewById(R.id.target).getBackground());
background.findDrawableByLayerId(R.id.border).setColorFilter(Color.CYAN, PorterDuff.Mode.SRC_IN);
I created two simple Drawables that utilize the ripple and are applied to a list of buttons generated by a RecylerView.
Drawable One:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ffffffff">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#android:color/doesnt_matter" />
<corners android:radius="3dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle" android:padding="3dp">
<solid android:color="#color/store_closed"/>
<corners android:radius="3dp"/>
</shape>
</item>
</ripple>
Drawable Two:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ffffffff">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#android:color/doesnt_matter" />
<corners android:radius="3dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle" android:padding="3dp">
<solid android:color="#color/store_closed"/>
<corners android:radius="3dp"/>
</shape>
</item>
</ripple>
In my adapter, I've set it up where the background of the button will be set to one of the two drawables, depending on an arbitrary boolean value.
if (isStoreOpen) {
storeOpen.setBackground(bgStoreOpen);
} else {
storeOpen.setBackground(bgStoreClosed);
}
Unfortunately, I get some weird behavior with the buttons. Sometimes, the ripples won't show up at all, and other times the ripple will appear on the button below it in the RecyclerView. Here's a video of what's happening (note I'm clicking on the bottom button): https://www.dropbox.com/s/ge5u7r7q2rfstnk/weirdRipples.mp4?dl=0
Any ideas? Thanks for your help, and let me know if you need any more of the code!
I am using a drawable as a background of a TextView just to have a divider line below the text. A achivied it with this drawable-xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
android:shape="rectangle">
<solid android:color="#FFDDDDDD" />
<gradient
android:angle="0"
android:startColor="#FFAAAAAA"
android:endColor="#FFEEEEEE"
/>
</shape>
</item>
<item android:bottom="2dp">
<shape
android:shape="rectangle">
<solid android:color="#FF000000" />
</shape>
</item>
</layer-list>
But this method draws a colored rectangle above a black rectangle. I would like to have just the line at the bottom of the shape with no black rectangle because black is not transparent. How could I achieve that?
This is how I got a line at the bottom for mine. Draw a stroke but then shift the item up and to the sides to get the top and sides to not show the stroke:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-8dp" android:left="-8dp" android:right="-8dp">
<shape>
<solid android:color="#2b7996"/>
<stroke android:color="#33b5e5" android:width="6dp"/>
</shape>
</item>
</layer-list>
I think it's better solution:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:gravity="bottom">
<shape>
<size android:height="1dp" />
<solid android:color="#000000" />
</shape>
</item>
</layer-list>
In general, I try to mess as little as possible with backgrounds unless absolutely necessary, since doing so overrides the default background colors that have states for focused, pressed, etc. I suggest just using an additional view (in a vertical LinearLayout) that is as thick as you need it to be. For example:
<View
android:background="#FF000000"
android:layout_height="2dp"
android:layout_width="fill_parent"/>
Usually for similar tasks - I created layer-list drawable like this one:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/underlineColor"/>
</shape>
</item>
<item android:bottom="3dp">
<shape android:shape="rectangle">
<solid android:color="#color/buttonColor"/>
</shape>
</item>
The idea is that first you draw the rectangle with underlineColor and then on top of this one you draw another rectangle with the actual buttonColor but applying bottomPadding. It always works.
But when I needed to have buttonColor to be transparent I couldn't use the above drawable. I found one more solution
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/transparent"/>
</shape>
</item>
<item android:drawable="#drawable/white_box" android:gravity="bottom" android:height="2dp"/>
</layer-list>
(as you can see here the mainButtonColor is transparent and white_box is just a simple rectangle drawable with white Solid)
With this solution where ever you require different line you can. My requirement was underline only. Even you can give different colors to the layout. You can see in below picture, white line
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-5dp" android:left="-5dp" android:right="-5dp">
<shape>
<solid android:color="#android:color/transparent"/>
<stroke android:color="#color/white" android:width="5dp"/>
</shape>
</item>
<item android:top="-5dp" android:bottom="-5dp" android:right="-5dp">
<shape>
<solid android:color="#android:color/transparent"/>
<stroke android:color="#color/colorPrimaryDark" android:width="5dp"/>
</shape>
</item>
<item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
<shape>
<solid android:color="#android:color/transparent"/>
<stroke android:color="#color/colorPrimaryDark" android:width="5dp"/>
</shape>
</item>
<item android:top="-5dp" android:left="-5dp" android:bottom="-5dp">
<shape>
<solid android:color="#android:color/transparent"/>
<stroke android:color="#color/colorPrimaryDark" android:width="5dp"/>
</shape>
</item>
<item android:bottom="2dp" android:left="5dp" android:right="5dp" android:top="5dp">
<shape>
<solid android:color="#color/colorPrimary"/>
<corners android:bottomRightRadius="0dp"
android:bottomLeftRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
</shape>
</item>
</layer-list>
This is a slightly lighter variant of the above.
/drawable/rect_highlight.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<stroke android:width="1px" android:color="#color/colorHighlight"/>
</shape>
/drawable/underline.xml
<inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="-1px" android:insetRight="-1px" android:insetTop="-1px" android:drawable="#drawable/rect_highlight"/>
Usage:
<TextView ... android:background="#drawable/underline"/>
It's not mine, somebody smarter than I came up with it. If I was smarter, I would have asked who. :)
This solution worked for most of the cases that I needed something like that.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/transparent" /> <!--background color of box-->
</shape>
</item>
<item
android:height="2dp"
android:gravity="bottom">
<shape>
<solid android:color="#000000" />
</shape>
</item>
</layer-list>
A simple solution is extending a TextView, then override the onDraw.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(ContextCompat.getColor(getContext(),R.color.colorTextUnderLine));
paint.setStrokeWidth(10);
canvas.drawLine(0.0f,canvas.getHeight(),canvas.getWidth(),canvas.getHeight(),
paint);
}