I have a custom view with a background drawable.
The drawable has an inside shape with padding. No padding is applied on the view itself.
Whenever I set a padding on the view programmatically using View.setPadding(left,top,right,bottom), the shape padding gets changed too and I honestly cannot figure out why.
The xmls are defined as follows:
Background drawable
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item>
<shape android:shape="rectangle">
<corners android:radius="#dimen/radius_large" />
<solid android:color="#color/yellow" />
<padding
android:left="#dimen/spacing_large"
android:right="#dimen/spacing_large"
android:top="#dimen/spacing_medium_to_large"
android:bottom="#dimen/spacing_medium_to_large" />
</shape>
</item>
</ripple>
Custom view extending ConstraintLayout (edited)
The tools: attrs on the <merge> tag are simply used to render what the outcome will be in the layout preview.
As you know, <merge> is not a viewgroup, so it doesn't allow attrs such as background etc
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"
tools:background="#drawable/background_start_lesson"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
... />
<ImageView
... />
<TextView
... />
</merge>
In the constructor of my custom view, I simply set the R.drawable.background_start_lesson
And this of course just renders nicely as expected, with large paddings:
.....but if I just set the padding of the view itself to 0dp programmatically or via xml (and it should be already at 0dp, given that I specified none on the view!), this is what happens:
In conclusion, why does setPadding() change the <shape> drawable padding and not the padding of the view?
Related
I have a LinearLayout view to which I need to set the background image programmatically. However, when this view gets the focus, I need to show a stroke around it.
What am I doing:
The background resource (view_onfocus_background.xml) to show onFocus effect:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<stroke android:width="5dp" android:color="#F7CA18" />
</shape>
</item>
</selector>
In the layout XML, I am adding the background as follows to apply the background with onFocus effect.:
android:background="#drawable/view_onfocus_background"
However, in the code, I have to set the different background image to the layout.
myLayout.setBackgroundResource(R.drawable.custom_image);
So, obviously, the view_onfocus_background I added in the layout XML doesn't apply anymore!
Question:
How can I achieve onFocus effect as well as custom image background to the layout?
I figured out that there is no way I can apply background effect through XML as well as the image background to the LinearLayout. The only thing I could do is to have two LinearLayouts (parent and child). Apply XML to the parent layout. Apply image background to the child layout. Add some padding in the parent layout to show the onFocus effect.
Example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/customFocusLayout"
android:padding="5dp"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:background="#drawable/view_onfocus_background"
>
<LinearLayout
android:id="#+id/customTestLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:padding="0dp"
android:layout_gravity="bottom"
android:background="#drawable/custom_image"
android:orientation="vertical">
<!-- more stuff here-->
</LinearLayout>
</LinearLayout>
In my Android application I have one view it may be ImageView or TextView how can I set shadow effect for View in android? I have set the shadow by using the following code, but it won't work:
view.setElevation(130)
Please help me to solve this
You can create your own "shadow view"
<View
android:id="#+id/shadow_view"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="bottom"
android:background="#drawable/shadow_gradient" />
and add the shadow drawable to it:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="#android:color/transparent"
android:startColor="#8f000000" />
</shape>
The height is up to you, to experiment and see what works best for you as is the angle and start colour of the drawable. You just need to align this view layout to any view layout you want to have a shadow and you are good.
I have a requirement to show a View which need to have a circular boundary.
I know it can be done by Extending the RelativeLayout. But exactly dont know what all methods to override except constructors and what code changes I have to make for it to show circular boundary.
Updated question with Image.
So basically this is an animation.
and minutely the view goes out from screen from the circumference of the circle (And not as rectangular view).
So I have to create a circular view (Relative Layout) that is having child of these images.
Use android.support.v7.cardview and put a RelativeLayout as its child.
https://developer.android.com/reference/android/support/v7/widget/CardView.html
Note from the above link:
Due to expensive nature of rounded corner clipping, on platforms
before L, CardView does not clip its children that intersect with
rounded corners. Instead, it adds padding to avoid such intersection
(See setPreventCornerOverlap(boolean) to change this behavior).
i think you need to make any layout with rounded border. using below code for make layout rounded.
round.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item><shape>
<solid android:color="#color/list_row_bg" />
<corners android:bottomLeftRadius="4dp"
android:bottomRightRadius="4dp"
android:topLeftRadius="4dp"
android:topRightRadius="4dp" />
<stroke android:width="1dp" android:color="#color/header_bg" />
</shape></item>
</selector>
put this round.xml file drawable folder. and use as backgournd in your layout.
my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="25dp" >
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/round" />
</LinearLayout>
I have a LinearLayout that looks like this.
I want each row to be clickable. The LinearLayout code for a row looks like this:
<LinearLayout
style="#style/home_menu_item_container"
android:id="#+id/home_menu_acronyms_button"
>
<ImageView
style="#style/home_menu_item_left"
android:background="#color/greyLight"
/>
<TextView
style="#style/home_menu_item_right"
android:text="#string/home_menu_option_2"
android:background="#color/grey"
/>
</LinearLayout>
How can I add a ripple effect that expands over the entire row (parent) - not just one child view in the row? The tricky part here is to let the ripple go over the two colored row.
So far, I found out the easiest way to do so is define a <ripple> in your drawable and then set the background of the LinearLayout to this drawable resource.
Define your drawable-v21/item_selector.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/your_background_color">
<item android:id="#android:id/mask"
<!--color here doesn't matter-->
android:drawable="#android:color/white" />
</ripple>
Set the background of your LinearLayout to drawable/item_selector.
<LinearLayout
style="#style/home_menu_item_container"
android:background="#drawable/item_selector"
android:id="#+id/home_menu_acronyms_button" >
...
</LinearLayout>
Besides, if you don't have your own background color, then there is no need to define a item_selector at all. You can simply define background as android:background="?android:attr/selectableItemBackground" for your LinearLayout.
It is a little bit complicated for that what you need but I don't think there is another way,...
You need to put your ImageView's into a ListView so that every ImageView is a ListItem and then you can set the ripple but you also need to set drawSelectorOnTop="true" otherwise it won't work correctly
I too faced this problem, finally found a simple solution
In linear Layout just add android:clickable="true";
and set background with ur ripple effect as
android:background="#drawable/ripple_effect"
code:
<LinearLayout
android:clickable="true"
android:background="#drawable/ripple_effect"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Add your child views here -->
</LinearLayout>
add ripple_effect.xml in drawable
ripple_effect.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#f87d05c2"
tools:targetApi="lollipop">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#f87d05c2" />
</shape>
</item>
</ripple>
<RelativeLayout
android:id="#+id/rll_privacy_policy"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="#+id/txt_privacy_policy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/layout_margin_16"
android:text="#string/privacy_policy"
android:layout_centerVertical="true"
android:textColor="#color/link_acc"
android:textSize="#dimen/txt_title_20" />
</RelativeLayout>
Another option is to make the ripple's background color transparent. This way only the ripple can be seen. The ripple's xml file (in your drawable-v21/ folder) is thus:
<-- Ripple in some ghastly color, like bright red so you can see it -->
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/red"
>
<!-- background color uses a transparent mask set to full #ffffff (white) -->
<item
android:id="#android:id/mask"
android:drawable="#android:color/white"
/>
Note that if you are supporting pre-lollipop devices, you need to have a dummy file with the same name in your drawable/ folder. An empty selector is sufficient for that file. And remember that those older devices will not ripple.
answer above dont work for me,
here is my solution:
ripple.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
>
...put het your design
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/ripple" />
</FrameLayout>
As described on Android Developer site:
A drawable defined in XML that insets another drawable by a specified
distance. This is useful when a View needs a background that is
smaller than the View's actual bounds.
http://developer.android.com/guide/topics/resources/drawable-resource.html#Inset
Instead of just moving the background and leaving the content in place in my case the inset is also moving the TextView.
This is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_inset"
android:orientation="horizontal" >
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text"
android:textSize="23sp" />
</LinearLayout>
This is the bg_inset drawable
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#android:color/darker_gray"
android:insetLeft="100dp" />
And this is the result I get:
By default, setting a background drawable also applies that drawable's padding to the view. Set the padding explicitly if you don't want it to match the background drawable.
Try to use shape with left-padding instead of inset:
<?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/darker_gray"/>
<padding android:left="100dp"/>
</shape>
Another option: if you want to use DP instead of PX, try my suggestion below. From my experience, InsetDrawable only works with pixels, which I find... unhelpful. To be honest, I am not happy with this solution, but hey, it works.
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="10dp"
android:drawable="#drawable/image_placeholder"
android:top="10dp" />
</layer-list>