I want to create a Custom Button with the following design using View and give it a drop shadow like the design below.1
The shadow options are: box-shadow: 10px 7px 25px 0px #0000001F
main_round_teamsbtn.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:padding="10dp"
android:shape="rectangle">
<solid android:color="#color/btn_color" />
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="105dp" />
</shape>
</item>
</layer-list>
teams_main_btn.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/main_round_teamsbtn"
android:paddingStart="16dp">
<TextView
android:id="#+id/teamsHead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/notosans_bold"
android:includeFontPadding="false"
android:text="원하는\n공모전을\n찾아보세요"
android:textColor="#color/black"
android:textSize="22sp"
app:layout_constraintBottom_toTopOf="#+id/teamsSub" />
<TextView
android:id="#+id/teamsSub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/notosans_regular"
android:text="현재 구하고 있는 팀 둘러보기"
android:textColor="#8C8C8C"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent" />
<ImageView
android:id="#+id/teamsImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:background="#drawable/findteams_btn"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0" />
</androidx.constraintlayout.widget.ConstraintLayout>
main.xml
...
<com.example.moizar.MainTeamsBtnView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
...
I want an answer how to give a shadow
I doubt you can achieve what you want by code, even if this is possible you will write a lot of code, probably involving RenderScript or some new APIs on Android 12...
consider using your image as 9-patch drawable with properly marked content/stretch areas. content (text?) would be full height and half width, stretch area only first pixels
teams_main_btn.xml
You can use attributes elevation in TextView or ImageView.
android:elevation= "10dp"
You can watch this link for more:
https://www.youtube.com/watch?v=nNHChjTZCtw&ab_channel=CodeAndDesign
I am trying to place an ImageView over a Button using RelativeLayout. Here is my xml:
<RelativeLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_weight="0.50" >
<Button
android:id="#+id/btnFindDaysInBetween"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue_500"
android:text="#string/dt_text_days" />
<ImageView
android:id="#+id/imageview_find_days_in_between"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/empty"
android:src="#drawable/ic_check_circle_white" />
</RelativeLayout>
Here is the image screenshot:
As you can see, the ImageView's src image is not visible. However if i change the button at the back to an ImageView, the image of the top ImageView is visible. Please refer below..
Changed xml:
<RelativeLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_weight="0.50" >
<!--
<Button
android:id="#+id/btnFindDaysInBetween"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue_500"
android:text="#string/dt_text_days" />
-->
<ImageView
android:id="#+id/imageview_find_days"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:contentDescription="#string/empty"
android:src="#drawable/ic_send_black" />
<ImageView
android:id="#+id/imageview_find_days_in_between"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/empty"
android:src="#drawable/ic_check_circle_white" />
</RelativeLayout>
Changed xml's screenshot:
What is it that i am doing wrong in the first layout?
The reason is actually very simple. :) We are so caught up thinking in 2D that we overlook the elevation - in Z.
There is nothing wrong with your first layout. The Button simply has a higher elevation than the ImageView - exactly 1dp higher. Therefore, no matter how you arrange the two views, the Button rises above.
A bit of proof:
A Button, by default gets the Widget.Material.Button style:
<!-- Bordered ink button -->
<style name="Widget.Material.Button">
<item name="background">#drawable/btn_default_material</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
<item name="minHeight">48dip</item>
<item name="minWidth">88dip</item>
<item name="stateListAnimator">#anim/button_state_list_anim_material</item>
<item name="focusable">true</item>
<item name="clickable">true</item>
<item name="gravity">center_vertical|center_horizontal</item>
</style>
The attribute that introduces this elevation is android:stateListAnimator. StateListAnimator is similar to StateListDrawable, and provides state change animations. The complete xml is here: Link. But here's the base state of the button:
<!-- base state -->
<item android:state_enabled="true">
<set>
<objectAnimator android:propertyName="translationZ"
android:duration="#integer/button_pressed_animation_duration"
android:valueTo="0"
android:startDelay="#integer/button_pressed_animation_delay"
android:valueType="floatType"/>
<objectAnimator android:propertyName="elevation"
android:duration="0"
android:valueTo="#dimen/button_elevation_material"
android:valueType="floatType" />
</set>
</item>
As you can see, the elevation value for the button is set to #dimen/button_elevation_material:
<dimen name="button_elevation_material">1dp</dimen>
And that's how the ImageView ends up being behind/below the Button.
So, what can we do?
A straight-forward solution would be to set the ImageView's elevation to the same amount - 1dp.
Another solution, which will require a bit of work, is to remove the Button's elevation rather than change ImageView's. Based on the default StateListAnimator, we can create our own - and remove the elevation. Then, in your res/values-v21/styles.xml, define a style that inherits from Widget.Material.Button:
<style name="MyDepressedButtonStyle" parent="android:Widget.Material.Button">
<item name="android:stateListAnimator">#anim/customized_state_animator</item>
</style>
Now, set this style on your Button:
<Button
style="#style/MyDepressedButtonStyle"
....
.... />
Edit:
Actually, we can apply the customized StateListAnimator directly:
<Button
android:stateListAnimator="#anim/customized_state_animator"
....
.... />
No need to take the scenic route!
I found a solution:
simply android:elevation="2dp"
<Button
android:id="#+id/btnAccess"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_gravity="right|center"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView4"
android:background="#drawable/or"
android:layout_alignBottom="#+id/btnRegister"
android:layout_centerHorizontal="true"
android:layout_margin="5dp"
android:elevation="2dp" />
Actually it's much easier to just set the StateListAnimator to #null
<Button
...
android:stateListAnimator="#null" />
Source Android 5.0 android:elevation Works for View, but not Button?
Use ImageButton replace Button and set ImageButton background as transparent.
<ImageButton
android:id="#+id/btnFindDaysInBetween"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/blue_500_text"
android:background="#android:color/transparent"
/>
<ImageView
android:id="#+id/imageview_find_days_in_between"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/empty"
android:src="#drawable/ic_check_circle_white" />
You can make a image that has your blue_500 color and text(that is easy to create), then set this image to your ImageButton. After that, your ImageView will see on the top of ImageButton.
Hope this help!
Button is just a TextView with a certain style applied to it, so if you replace Button with TextView you can display an ImageView on top of it. This also works on API < 21.
android:background exists for all the view. As the name suggests this is what is going to be there in the background.
android:src exists for ImageViews and its subclasses. You can think of this as the foreground. Because ImageView is a subclass of View you even have android:background for that.
If the foreground is smaller than background, the background portion which is not covered by the foreground would be visible.
Also, you can use transparency in the foreground in which case the background would be visible(transparently).
You can use BACKGROUND FOR ALL THE VIEWS.. But You can use SRC only for ImageView & ImageButton.....
#Vamsi I tried your both combinations and first one is not working with Button. You have to go through ImageView. This is what I tried with with ImageView:
While I tried to do it with Button and see what was result:
I tried to change the order but all in vain! It seems you have to go with either ImageView or ImageButton.
At the end! You can see what I had tried:
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<!-- <ImageView
android:id="#+id/btnTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/ic_launcher_web"
android:contentDescription="#string/app_name"
android:text="#string/app_name" /> -->
<ImageView
android:layout_width="wrap_content"
android:id="#+id/imgView"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/app_name"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/btnTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/imgView"
android:layout_alignTop="#+id/imgView"
android:text="#string/app_name" />
</RelativeLayout>
I had done same kind of work either with ImageView or ImageButton (probably with ImageView) and tried same approach as you were trying with Button.
Thanks
If you want to get an ImageView on top of a Button, and you are developing for Android API < 21 (for instance, KitKat = 19), the easiest way is to not use a Button at all and use 2 ImageView instead. Why would you want to do that? May be because you defined a drawable shape to make the button look "cooler", so you are already using android:background with that shape.
Ex:
<Button
android:id="#+id/button01"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/buttonshape"
/>
<ImageView
android:id="#+id/image01"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:src="#drawable/desiredImageOnTop"
/>
Where #drawable/buttonshape.xml is:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="30dp"
/>
<gradient
android:angle="45"
android:centerColor="#47A891"
android:centerX="35%"
android:endColor="#000000"
android:startColor="#E8E8E8"
android:type="linear"
/>
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp"
/>
<size
android:width="100dp"
android:height="100dp"
/>
<stroke
android:width="3dp"
android:color="#878787"
/>
</shape>
In that case, you should replace the Button with an ImageView, change android:background to android:src, and then, in the java code, you just add an OnClickListener as if it was a Button (both controls derive from View, and OnClickListener is a View event). Works like a charm!
Actually, This is not an error, it is a simple design issues. I have been working on it for last 2 hours. And at last get an easy way.
Now, I want to share the code.
<FrameLayout
android:layout_alignParentStart="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:background="#drawable/custom_button"
android:paddingLeft="33dp"
android:layout_marginStart="33dp"
android:text="CHECK APPOINTMENT"
android:textAlignment="viewEnd"
android:textSize="18sp"
/>
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="60dp"
android:layout_height="wrap_content"
app:cardCornerRadius="40dp">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:elevation="2dp"
android:src="#drawable/care_logo"
android:scaleType="fitCenter"
/>
</androidx.cardview.widget.CardView>
</FrameLayout>
It is working.
I placed ImageView on a Button with a diversion of RelativeLayout, hope this helps.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<View
android:id="#+id/tempview"
android:layout_width="0dp"
android:layout_height="0dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/tempview"
android:background="#drawable/ic_launcher" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/tempview"
android:src="#drawable/img_cancel" />
</RelativeLayout>
I've searched around online for a solution to this problem and have tried out different ways of doing this but haven't come up with an answer. I have a list view and a custom row layout for the rows of the list. In my list row xml file there is a relative layout with an ImageView and text. Along with that I set the background of this relative layout to a certain shape and this works fabulous. Now at runtime I want to change this list row background to appear pressed inwards ( I was thinking just make the padding a little smaller or something). I have tried making another xml file for a pressed shape but it hasn't worked. I also tried to code this up by doing something such as this:
RelativeLayout rl = (RelativeLayout)view.findViewById(R.id.relativerow);
rl.setBackgroundResource(R.drawable.item_shape_pressed);
I'm guessing I'd have to make my own onPressed method for this to work?
Here is the shape xml file I am using for each list row background:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_shape">
<padding android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
<corners android:radius="20dp" />
<solid android:color="#FFF" />
</shape>
Here is the XML for each row in the list view. See where I sit the background attribute at the top.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativerow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/item_shape"
android:padding="5dip" >
<LinearLayout android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip">
<ImageView
android:id="#+id/list_image"
android:layout_width="60dip"
android:layout_height="60dip"/>
</LinearLayout>
<TextView
android:id="#+id/articletitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/thumbnail"
android:layout_toRightOf="#+id/thumbnail"
android:textColor="#040404"
android:typeface="sans"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="#+id/articldesc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/articletitle"
android:textColor="#343434"
android:textSize="13sp"
android:textStyle="italic"
android:layout_marginTop="1dip"
android:layout_toRightOf="#+id/thumbnail"
/>
</RelativeLayout>
So, is there any way for me at runtime to change the background in this relative view from the normal item_shape to another pressed in item shape? If anyone could show me how to do this I would certainly appreciate it. This is just a small part of the app that has been bugging me recently but it would be a nice touch to make the app look more complete.
Try with create your own selector for the ListView, for example listview_item_selector.xml in res/drawable folder and add this selector in the background of your RelativeLayout.
The following code will be: listview_item_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/item_shape_pressed" android:state_pressed="true" />
<item android:drawable="#drawable/item_shape_focused" android:state_focused="true" />
<item android:drawable="#drawable/item_shape" />
</selector>
And in your RelativeLayout put:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativerow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/listview_item_selector"
android:padding="5dip" >
.....
Currently I have following layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/editorRootView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout android:id="RL1"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1">
<!-- LinearLayout needed so we have an border outside of the EditorView -->
<LinearLayout android:id="LL1"
android:background="#drawable/border"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<xenolupus.EditorView
android:id="#+id/editorView"
android:layout_width="300dip"
android:layout_height="216dip" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:orientation="horizontal" >
<Button
android:id="#+id/otherImage"
android:layout_width="150dip"
android:layout_height="60dip"
android:text="#string/cardEditor_OtherImageButtonText" />
<Button
android:id="#+id/next"
android:layout_width="150dip"
android:layout_height="60dip"
android:text="#string/cardEditor_NextButtonText" />
</LinearLayout>
</LinearLayout>
And the used #drawable/border:
<?xml version="1.0" encoding="UTF-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#FFFFFF" />
<stroke
android:width="10dip"
android:color="#FF0099CA" />
<padding
android:left="10dip"
android:top="10dip"
android:right="10dip"
android:bottom="10dip" />
<corners
android:radius="5dip" />
</shape>
However Eclipse warns me (yellow triangle with !) that the LinearLayout LL1 in the RelativeLayout RL1 is useless and should be removed:
This LinearLayout layout or its RelativeLayout parent is useless;
transfer the background attribute to the other view.
As the RelativeLayout is needed to center the EditorView I tried removing the LinearLayout LL1 and adding the android:background of the LinearLayout LL1 to the EditorView. However doing lets the border disappear behind the content of the EditorView.
Is there another way to add a border outside of the EditorView or should I just ignore the warning?
Greetings
Xeno Lupus
yes it's right, put the background inside your <xenolupus.EditorView
like this
<xenolupus.EditorView
android:background="#drawable/border"
android:padding="10dp"
android:id="#+id/editorView"
android:layout_width="300dip"
android:layout_height="216dip" />
and then add gravity to it parent the RL1 layout
> android:gravity="center"
View can draw background by default. If you developed you EditorView correctly, you can just set background and paddings directly in XML:
<xenolupus.EditorView
android:id="#+id/editorView"
android:layout_width="300dip"
android:layout_height="216dip"
android:background="#drawable/border"
android:padding="10dp" />
By "developed correctly" I mean that your view calculate it's width in height (in onMeasure or onSizeChanged methods) with paddings. In other words: while calculating size you used getPadding*() methods.
NOTE
Do not forget to call super.onDraw() !
How can i wrap elements in the XML code in a box like view? meaning that i want them to be looking like they are grouped in some box with borders.
<Button
android:id="#+id/carbgraph"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="230dp"
android:layout_y="378dp"
android:text="Button" />
<ProgressBar
android:id="#+id/progressBarforcals"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_x="15dp"
android:layout_y="346dp" />
<TextView
android:id="#+id/calsinmenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="16dp"
android:layout_y="320dp"
android:text="TextView" />
Put your widgets in a layout (LinearLayout for example) and edit this layout background as below:
<LinearLayout
...
android:background="#drawable/background"
</LinearLayout>
Then create an XML file in your drawable folder named background.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="3dp"
android:color="#838c7f">
</stroke>
<padding
android:left="3dp"
android:top="3dp"
android:right="3dp"
android:bottom="3dp">
</padding>
<corners android:radius="4dp" />
<gradient
android:startColor="#color/background_start"
android:endColor="#color/background_end"/>
</shape>
You can set background of your layout
create one image that looks like box with border named box.png
put this image in drawable
ex:
<LinearLayout
.. ..
android:backgroud="#drawable/box.png">
<Button
android:id="#+id/carbgraph"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="230dp"
android:layout_y="378dp"
android:text="Button" />
<ProgressBar
android:id="#+id/progressBarforcals"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_x="15dp"
android:layout_y="346dp" />
<TextView
android:id="#+id/calsinmenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="16dp"
android:layout_y="320dp"
android:text="TextView" />
</LinearLayout>
There is also another way...
You can add a background color to the outer view(ex. black), then a different background color to the inner view(ex. white), add margin to the inner view and you 're done!