Change background Drawable padding dynamically - android

I want to Create a View that receives a percentage and displays only this part of background dynamically, as a parameter.
E.g. when creating a view with parameter 0.8; the background is drawn only in 80% of View width (0% padding left, 20% padding right).
I tried to create a DrawableGradient as a View background, but it overlaps whole background and I cannot resize this background.
My next choice was to create InsetDrawable or Layer-List like in this answer: Android drawable with background and gradient on the left, but I cannot change the padding dynamically.
The example I use currently:
res/layout/acitvity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="5dp"
tools:context=".MainActivity" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/percentage_background_80"
android:text="80%"
android:textSize="16sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/percentage_background_20"
android:text="20%"
android:textSize="16sp"/>
</LinearLayout>
drawable/percentage_background_20.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="5dp"
android:drawable="#drawable/background"
android:left="5dp"
android:right="5dp"
android:top="5dp"/>
<item
android:bottom="5dp"
android:drawable="#drawable/view_background"
android:left="5dp"
android:right="200dp"
android:top="5dp"/>
</layer-list>
drawable/percentage_background_80.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="5dp"
android:drawable="#drawable/background"
android:left="5dp"
android:right="5dp"
android:top="5dp"/>
<item
android:bottom="5dp"
android:drawable="#drawable/view_background"
android:left="5dp"
android:right="50dp"
android:top="5dp"/>
</layer-list>
drawable/background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#android:color/white" />
</shape>
drawable/view_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item><shape>
<gradient
android:angle="0"
android:startColor="#android:color/holo_blue_dark"
android:endColor="#android:color/white"
android:type="linear" />
</shape>
</item>
</selector>
This is how it looks, but I cannot change the values of padding in a list from a source code. Do you know how can I achieve it?
Clarification:
in drawable/percentage_background_80.xml and drawable/percentage_background_20.xml there are elements:
android:right="XXXdp"
I want to change the values XXXdp programatically.

either use ClipDrawable or ScaleDrawable depending on wheter you just want to clip target Drawable or resize it

Need add to:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/percentage_background_80"
android:padding="your_padding"
android:text="80%"
android:textSize="16sp"/>
This should works. For dynamically, please read this:
— how to manually set textview padding?
— Adding Margins to a dynamic Android TextView
EDIT:
Also, you may add your TextView to layout and change background, like this:
<LinearLayout
android:id=#"+id/your_id"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/percentage_background_80"
android:text="80%"
android:textSize="16sp"/>
</LinearLayout>
And in your class just use method findViewById and set background.

Related

I want to add strokes to a view

I'm trying to add strokes to a view using drawable.
But I want add it only in side parts(left and right), not in whole parts.
Is there any good way to add stroke in side parts?
Below is my drawable xml code. (leanear_border_gray.xml)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp"
android:color="#778899"/>
</shape>
and below is my target view xml code.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/linear_border_gray"
android:layout_weight="1">
....
</LinearLayout>
You need to wrap your shape into layer-list drawable with rectangular shape, add stroke and using top and bottom margins with negative values "hide" top and bottom lines, like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-4dp" android:bottom="-4dp">
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="#778899"/>
</shape>
</item>
</layer-list>
You can do it by using layer-list drawable suggested by #iDemigod
Your Layout should be like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_marginTop="20dp"
android:background="#drawable/border_left_right"
android:layout_gravity="center"
android:layout_weight="1">
</LinearLayout>
Note: If you are giving android:layout_height="match_parent" and android:layout_weight="1" then you must have to set android:layout_width="0dp" and vice versa for android:layout_width="match_parent".
File: border_left_right.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-4dp" android:bottom="-4dp">
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="#07060b"/>
</shape>
</item>

Ripple effect over imageview

To describe my problem i created small example.
I have linearlayout with imageview and textview. For linearlayout i've set ripple drawable as background. But when i click or long click on linearlayout ripple animation shows under imageview. How show animation over imageview ?
main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linear"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#drawable/ripple"
android:clickable="true"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:src="#mipmap/index" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is ripple test"
android:textColor="#FF00FF00" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
drawable-v21/ripple.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#FFFF0000">
<item>
<shape android:shape="rectangle">
<solid android:color="#FF000000"/>
</shape>
</item>
</ripple>
drawable/ripple.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#FFFF0000" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#FFFF0000" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#FF000000" />
</shape>
</item>
</selector>
screenshot how it looks now:
Add the ripple like this
android:foreground="?android:attr/selectableItemBackground"
based on this answer https://stackoverflow.com/a/35753159/2736039
Add android:background="#null" for the ImageView
If your app needs to run on API < 23, you won't be able to use the foreground attribute on views other than FrameLayout, which means adding another [useless] level in the view tree hierarchy.
Another solution is to wrap your image with a <ripple>, set it as your ImageView's background, and use tint and tintMode to "hide" the src image so the background image that has the ripple over it is visible.
<!-- In your layout file -->
<ImageView
android:adjustViewBounds="true"
android:background="#drawable/image_with_ripple"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/image"
android:tint="#android:color/transparent"
android:tintMode="src_in" />
<!-- drawable/image_with_ripple.xml -->
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?colorControlHighlight">
<item android:drawable="#drawable/image" />
</ripple>
Not only this works on API 21+ but if your image has rounded corners – or is another type of non-rectangle shape, like a star or a heart icon – the ripple will remain in its bounds instead of filling the view's rectangle bounds, which gives a better look in some cases.
See this Medium article for an animated GIF to see how this technique compares to using a <FrameLayout> or the foreground attribute.
Resolve for API < 21
<ImageView
android:id="#+id/favorite_season"
style="?android:attr/borderlessButtonStyle"
android:background="?android:attr/selectableItemBackground"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_margin="22dp"
android:clickable="true"
android:focusable="true"
android:src="#drawable/ic_star"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
Simple use these two lines as attribute in that ImageView.
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"

Shadow Layout with 9-patch and background color transparent?

I would like to add a custom layout an edge with shadow, exactly one like this:
http://inloop.github.io/shadow4android/
The problem is that I use this to add a semi / transparent background color: (corners_main_layout.xml)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="6dp" />
<solid android:color="#color/bright_foreground_disabled_material_dark" />
</shape>
So I can not use for background 9-patch.
Is there any way to 9-patch with shadows and transparent background color?
If not .... How could make the effect?
PS: I have seen many custom XML to add shadows, but all are very poor.
Here example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_recover_pass"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="...RecoverPassActivity"
android:background="#mipmap/fondo_01"
android:orientation="vertical">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/corners_main_layout">
</LinearLayout>
I Need shadow border rectangle White (it is transparent) similar to example 9-patch
------------EDIT---------------
I modified mi corners_main_layout.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="6dp" />
<solid android:color="#color/bright_foreground_disabled_material_dark" />
</shape>
</item>
<item android:drawable="#drawable/shadow_custom" />
and result :-( :
yeah! i have solution!
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp" />
<solid android:color="#color/bright_foreground_disabled_material_dark" />
</shape>
</item>
<item android:drawable="#drawable/shadow_custom_9patch"/>
</layer-list>
thanks for help!

How to round corners of list item at the top and bottom of the list view? (not only for top and bottom items)

I have a listview with rounded corner at the top and the bottom. Look like this image:
But when I click on the top and the bottom of ListView, the List Item's background is rectangle not rounded as background of ListView at top and bottom. Like this image :
How to resolve this issue?
this is my code :
1/ list_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cacaca">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/list_border"
android:listSelector="#drawable/list_selector"/>
</LinearLayout>
2/ list_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
</shape>
3/ list_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#color/colorPrimary" />
</selector>
4/ ListActivity.java
ListView listView = (ListView)findViewById(R.id.listView3);
ArrayList<String> listItems = new ArrayList<>();
for(int i=0;i<20;i++){
listItems.add(""+i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_selectable_list_item, listItems);
listView.setAdapter(adapter);
This solution is not pretty but it does what you want. The idea is to invert the corner and draw them as foreground :
the ListView is wrapped in a FrameLayout :
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:foreground="#drawable/inverted_corners"
android:layout_weight="1">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:listSelector="#drawable/list_selector" />
</FrameLayout>
which foreground (drawable/inverted_corners.xml) is set to a rounded hole, drawn with the background color. The trick is to draw a line outside the shape, instead of a filled shape :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-11dp"
android:left="-11dp"
android:right="-11dp"
android:top="-11dp">
<shape android:shape="rectangle">
<stroke
android:width="10dp"
android:color="#cacaca" />
<corners android:radius="22dp" />
</shape>
</item>
</layer-list>
This garanties that the rounded corners are on top of the selector, and the overscroll effect.
I suggest you should set the layout with corners to your ListView's first and last element, but not to the whole ListView.
You can create two extra .xml files in addition to your list_selector.xml: one for first element with the round corners at the top (lets call it list_selector_top.xml) and another one for the last element with the round corners at the bottom (list_selector_bottom.xml).
Then you can create your own MyAdapter extends ArrayAdapter and somewhere in getView() method set the appropriate background to your element's View (if position==0 set list_selector_top.xml, if position==getCount()-1 set list_selector_bottom.xml, by default set list_selector.xml).
It might be not the simpliest approach, but it works.
Set your corner radius to list view selector also using this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/list"
android:state_pressed="true"
>
<shape>
<solid android:color="#color/colorPrimary"/>
<corners
android:radius="10dp"/>
</shape>
</item>
</selector>
so your selection will not be cross boundry of list view.
cons - you will not able to define which radius you have to set as per top and bottom part that is why have to set radius to all sides.
hope this should help or at least give you some direction to resolve your issue.
If you can use FrameLayout as parent to the ListView, then set the cornered shape as foreground to the parent FrameLayout.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/list_border">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="#drawable/list_selector"/>
</FrameLayout>
If you want to use LinearLayout as parent of ListView, then surround your ListView with ForegroundLinearLayout and set the cornered shape as foreground to the ForegroundLinearLayout.
What is ForegroundLinearLayout? It is LinearLayout with Foreground property like FrameLayout. Get the code from Chris Banes. https://gist.github.com/chrisbanes/9091754
Your code should be:
<?xml version="1.0" encoding="utf-8"?>
<ForegroundLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/list_border">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="#drawable/list_selector"/>
</ForegroundLinearLayout>
please add padding in your style.i updated style here.
2 list_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<padding android:left="10dp"
android:right="10dp"
android:top="10dp"
android:bottom="10dp"
/>
</shape>
This can be done easily by using Android's support library's CardView. Just wrap your ListView in a CardView layout and set a cardCornerRadius to the CardView, like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cacaca">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
card_view:cardCornerRadius="10dp"
>
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:listSelector="#drawable/list_selector"/>
</android.support.v7.widget.CardView>
</LinearLayout>
Dont forgot to import the CardView's support library:
compile 'com.android.support:cardview-v7:23.1.1'

Drawable padding overrides layout padding

I have a TextView like so:
<TextView
android:id="#+id/friends"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp" />
And I'm setting the background like:
textView.setBackgroundResource(R.drawable.background_color);
where background_color.xml is:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#217dd2" />
</shape>
</item>
<item
android:left="5dip">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#deebf6" />
</shape>
</item>
This removes my default padding of 8dp and replaces it with the left padding of 5dp that I have declared on the 2nd item of the layered-list. Any way to avoid this? Or another way to create a 2 color background for a View?
That's known issue, setBackgroundResource method resets paddings.
Try to set your background from XML:
<TextView
android:id="#+id/friends"
android:background="#drawable/background_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp" />
It will work properly in this case.

Categories

Resources