CardView compatibility problems on Pre-Lollipop - android

I have some problems using the new CardView
That's my current situation: I want to use a CardView to provide a Floating Action Button for all devices (also Pre-Lollipop)
my activity's layout looks like this
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cdcdcd"
android:focusable="false">
<include layout="#layout/toolbar"/>
<android.support.v7.widget.CardView
android:layout_width="58dp"
android:layout_height="58dp"
cardview:cardPreventCornerOverlap="true"
android:layout_gravity="bottom|right"
android:layout_marginBottom="16dp"
android:layout_marginRight="18dp"
cardview:cardCornerRadius="29dp"
cardview:cardBackgroundColor="?attr/colorPrimary">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_margin="12dp"
android:src="#android:drawable/ic_menu_edit"/>
</android.support.v7.widget.CardView>
Running the app on a Nexus 5 (4.4.4) the screen looks like this:
now I want to set the cardElevation by setting this in the xml
cardview:cardElevation="8dp"
After starting the app the button looks like this (it isn't a circle anymore):
It seems setting the card elevation also affects the view's dimensions... If you take now a closer look to picture #1 you can see, that this button isn't also a perfect circle.
Is there a way to figure that out? I also tried to set this
cardview:cardPreventCornerOverlap="false"
But it also has no affect
Thanks guys :)

Using CardView for FAB shadows is not the best idea. CardView is a layout, so it's pretty heavy. It's also very limited on pre-Lollipop versions. The shadow is not animated, corners pad the content and there's no ripple. Seems like there's no good method to achieve 100% FABs using only AppCompat.
In general I'm not happy being limited to AppCompat, so I wrote my own Button classes based on regular ones. I was able to achieve pretty good results as you can see on the screenshot. It's Gingerbread and there are animated shadows, ripples, vector graphics, etc. It's a pretty large repository, so I'm unable to give you a short solution here, but if you wish, check out the code on github.

You could try using the FAB from this MaterialDesign library if you're desperate for the shadow effect on older devices.
You can find the library at https://github.com/navasmdc/MaterialDesignLibrary
<com.gc.materialdesign.views.ButtonFloat
android:id="#+id/buttonFloat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="24dp"
android:background="#1E88E5"
materialdesign:animate="true"
materialdesign:iconDrawable="#drawable/ic_action_new" />
Alternatively you could create your own shadow resource in your drawables folder, and add the shape below your button, something like this:
<shape android:shape="oval"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/black_alpha"/>
<corners android:radius="20dip"/>
And create a layer list resource where you include your button and the shadow
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/shadow"/>
<item
android:drawable="#drawable/button"
android:bottom="4px" />
</layer-list>

Related

Remove border from Borderless button

I have this button:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/AppTheme.Button.Toolbar"/>
And this style:
<style name="AppTheme.Button.Toolbar" parent="Widget.AppCompat.Button.Borderless">
<item name="colorButtonNormal">#color/main</item>
<item name="android:textColor">#color/secondary</item>
</style>
Even though the style inherits from Widget.AppCompat.Button.Borderless, the button still has a border.
Changing Button to android.support.v7.widget.AppCompatButton did not help.
How to remove the border then?
Edit:
Setting background of the button is not an option - by doing so the animation of ripple effect is lost.
Edit 2:
Things become even more interesting.
Tried to change android:theme to style as #cadet suggested.
When button is defined this way:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/ToolbarButton"/>
That's what I get:
The colors apply, but there is distinct border.
If I just change theme to style:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
style="#style/ToolbarButton"/>
I get this:
There is no border, and the style is applied only partially (text is colored, button is not)
Edit 3:
Friends, I'm looking for a way to get borderless, styled button with ripple effects using styling approach. Hacking each and every button separately in layout files might work, but that's not the point.
Try this, hope out of this one may help you
<Button
android:id="#+id/btn_photo_lib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startPhotoLibAction"
android:src="#drawable/library_blau_2"
style="?android:attr/borderlessButtonStyle"/>
or
android:background="#null"
set background #null. or set own created background
android:background="#null"
You can use a different View instead of Button
<LinearLayout
android:id="#+id/btn_action_alternative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:clickable="true" />
I found a better solution, you'll wanna create a custom drawable and depending on the min version your app supports, you'll need to create two, one for Android versions pre-21(Lollipop) and another for post 21(Lollipop). The two files will need to be named identically so Android can find them and match them appropriatly based on the API level. But in the file drawable file for API 21 and above your file should look like such:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:drawable="#drawable/button_normal"/>
</ripple>
This Drawable file is wrapping another Drawable that is your preferred background image or color with a ripple whose color is defined using "?android:colorControlHighlight", which is simple a reference to a default color from what ever theme the current activity is using.
If you need to support pre-21(Lollipop), your drawable file would simply be a selector, with the preferred drawable. Your preferred drawable should be the same background color, or even a transparent color to make sure you can see your parent layouts background color. Similar to this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_normal"/>
</selector>
You can combine this with a style in order to apply the borderless style to all buttons it to all buttons in a layout... I recommend you use a transparent drawable so you can use this style with all buttons regardless if their parent has a different color background. This will prevent you from making several themes with different backgrounds.
To handle versioning support, or even config support if you'd like custom drawables based on various device configurations, you would just create several drawable folders with a configuration specific suffix. So, for example, drawables only for version 21 and above you'd create a folder called 'drawable-21'.
I found a website that better explains what I'm talking about.

Style TextView like a Spinner with appcompat v21

I want to make a TextView look like a spinner with the new Material style.
I managed to do it with "Widget.Material.Light.Spinner" style, but I didn't find any alternative in AppCompat (v21) resources.
My xml:
<TextView
android:id="#+id/sp_league_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
tools:text="Premier league"
style="#android:style/Widget.Material.Light.Spinner"
android:textColor="#android:color/white" />
I'd go with:
style="#style/Widget.AppCompat.Spinner"
But feel free to pick another one:
The style solution didn't work for me, but I've found another solution:
I use AppCompatButton instead, and have this :
XML:
<android.support.v7.widget.AppCompatButton
android:background="#drawable/abc_spinner_mtrl_am_alpha"
... />
Java:
((AppCompatButton)findViewById(...)).setSupportBackgroundTintList(new ColorStateList(new int[][]{new int[0]}, new int[]{0xff52A1E8}));
EDIT: seems it won't work well anymore, but found another solution :
<style name="Widget.MyTheme.HeaderBar.Spinner" parent="Widget.AppCompat.Light.Spinner.DropDown.ActionBar">
</style>
It's true that it's for the action bar , but it should work for other cases too.
I Tested the the solutions mentioned here 1.Using style="#style/Widget.AppCompat.Spinner) and
2.Using Widget.AppCompat.Light.Spinner.DropDown.ActionBar
Both these works only on Android 5.x And Above Devices and do not work well for Android devices running on 4.x and below.
Hence, I am posting my solution for those who wanted to have a Drop-down like effect to TextView for all devices.
App needs to create a Drawable inside drawable folder in App, let's say dropdown_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/ic_icon_arrow"
android:gravity="end" />
And then simply use this as a background for the TextView as below:
<TextView
android:id="#+id/mySpinnerTextView"
android:background="#drawable/dropdown_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
In AndroidX, use style="#style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem"

How to make a View clickable that's underneath another already clickable View?

It was hard to give a descriptive title for this question!
I have an app widget in which I have some clickable buttons (using RemoteViews and PendingIntents as needed for app widgets) that are difficult to tap at their current size. To work around this without having to resize the actual button, I have placed larger, invisible, clickable FrameLayouts over these buttons to increase the clickable area. This works well, except the buttons also have selectors connected to them so that the background color for the images change when tapped. This selector no longer works when the FrameLayout covers the buttons since it's now actually the FrameLayout that's being tapped, not the buttons.
My question is if there's a way to somehow make it "click through" the FrameLayout so that the selector for the button is still triggered, or any other clever workaround that achieves the same effect? Applying the selector on the FrameLayout itself will make the background change much too large.
Below is a simplified example of what I'm doing. The actual layout I'm using is more complex, so any solutions that requires changing the layout may be more difficult to do than it may seem here. Also, the reason the FrameLayout is placed in a RelativeLayout is so that I have more freedom with the placement.
EDIT
The FrameLayout is placed on top of two other layouts, which is why I can't simply place it under the button. It needs to cover a larger area. I'm hoping I won't have to redo the entire layout to fix this problem.
LAYOUT
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageButton
android:layout_width="#dimen/size_myButton_w"
android:layout_height="#dimen/size_myButton_h"
android:layout_alignParentRight="true"
android:background="#drawable/selector" //NOT TRIGGERED! Covered by FrameLayout below.
android:src="#drawable/myButton" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!-- More stuff here! -->
</RelativeLayout>
<!-- Even more stuff here! -->
</LinearLayout>
<FrameLayout
android:layout_width="120dp"
android:layout_height="35dp"
android:layout_alignParentRight="true">
</FrameLayout>
</RelativeLayout>
SELECTOR
<?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/navy" />
<item android:state_focused="true" android:drawable="#color/white" />
<item android:drawable="#color/white" />
</selector>
Perhaps you could place your FrameLayout below the button, rather than on top. That way if they hit the actual button, you get your selector triggered and if they miss the button and still hit the FrameLayout...well, your selector won't get triggered, but your FrameLayout click listener will still get called.

Android fly-in menu shadow

I have been toying with a few different libraries and code snippets for the past few days. I am trying to create a menu like the one seen in the facebook app.
Now there are many libraries and resources on building something of that kind, but I'm having major difficulties in drawing a shadow between the 'top' and 'bottom' page as to create the illusion that the 'top' page is actually on top.
Now the exact effect Im trying to create is displayed in this article:
http://android.cyrilmottier.com/?p=717
The author of the article I got this from is not very thorough in his explanation. This could be due to my programming-skills-under-development, or maybe I'm not the only one.
I'm using the following library and example app to test and develop with:
https://github.com/jfeinstein10/SlidingMenu
I would be very happy if anyone could help me get this to work.
PS: I'm very sorry, but since I'm a newbie here I am not allowed to post any pictures.
What I did is I'm putting a shadow at the right of my menu view (ie behindView) with a margin on the right of your above view :
<!-- Show shadow on the right of the menu -->
<RelativeLayout
android:id="#+id/menuShadow"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="false"
android:clickable="false"
android:background="#00000000"
android:layout_marginRight="40dp">
<ImageView
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_width="6dp"
android:layout_height="fill_parent"
android:background="#layout/border_menu_progressive_shadow"/>
</RelativeLayout>
With my shadow layout:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#00101010"
android:endColor="#252525"
android:angle="0" />
</shape>
</item>
</selector>

Android Home Screen Widget (icon, label - style)

I'm trying to create an icon/widget (1 cell x 1 cell) that can be placed on the home screen of android. The widget will look and act exactly like the other standard shortcuts in android. It will have an icon and under that a label, it will be selectable with the trackball (highlight able) it will be highlighted when it is selected/clicked.
How do I go about creating this home screen widget?
Do I have to create the widget myself using code/xml or is there some standard xml, style, theme, code that I can use to ensure that the widget will have the same style/theme as the other home screen widgets?
I currently have the following
res/drawable/corners.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Corners">
<stroke android:width="4dp" android:color="#CC222222" />
<padding android:left="4dp" android:top="1dp" android:right="4dp" android:bottom="1dp" />
<corners android:radius="4dp" />
</shape>
res/layout/widget.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Widget"
android:layout_width="72dip"
android:layout_height="72dip"
android:orientation="vertical"
android:focusable="true"
android:gravity="center_horizontal"
style="#android:style/Widget"
>
<ImageView
android:id="#+id/WidgetIcon"
android:src="#drawable/icon"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:paddingTop="3dip"
android:gravity="center"
/>
<TextView
android:id="#+id/WidgetLabel"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="#string/app_name"
android:textSize="15dip"
android:background="#drawable/corners"
/>
</LinearLayout>
The resulting widget looks some what close, but its not selectable, it doesn't get highlighted when clicked and the label isn't exactly in the correct location or the correct style.
Any ideas, if there is a correct way to do this, or should I just keep working away on the above until I am closer?
The "correct way to do this" is to make a shortcut, and not try to mimic it with an app widget. This has been pointed out repeatedly by the core Android team (notably Romain Guy) on the [android-developers] discussion list, such as:
Widgets should look like widgets, not
like shortcuts. The main reason is
that there is absolutely NO guarantee
about what a shortcut will look like.
Other devices (especially ones with
custom system UIs like MOTOBLUR or HTC
Sense) might have a different look and
feel. Or in the next update of Android
we might change the way shortcuts are
presented.
To make your item consistent with the system look and feel is not hard by referencing the system attribute android:attr/selectableItemBackground. For example, if you want to make an ImageView in your widget look "selectable" with proper highlighting etc: just do
<ImageView
...
android:background="?android:attr/selectableItemBackground"
...
/>
There are a lot in android_sdk_path/platforms/android-x. Happy digging!
EDIT: I found out later that this simple attribute does not live in SDK < v11. So the best way I know now is to download the appwidget template pack and use it.

Categories

Resources