I have a ListView, and it works great on a phone. Now I am making a tablet UI, with the ListView on the left and details on the right.
When I touch an item, it flashes blue as long as it is pressed. I want to keep that blue color until another item is selected, just like the Gmail app on the Nexus 7.
What is the cleanest way to achieve that? I'd rather avoid setting backgrounds manually, I assume there is a way to mark an element as the "active" one and theme it accordingly.
What is the cleanest way to achieve that?
What you are looking for is known as the "activated" state. To make this work:
Step #1: In res/values-v11/, have a style resource that implements activated. For example, for a new project that has the AppTheme declaration defined there, go with something like:
<resources>
<style name="AppTheme" parent="android:Theme.Holo.Light"></style>
<style name="activated" parent="AppTheme">
<item name="android:background">?android:attr/activatedBackgroundIndicator</item>
</style>
</resources>
Step #2: Define the same style in res/values/ for any older devices, just as a stub style resource, so references to it continue to work:
<resources>
<style name="AppTheme" parent="android:Theme.Light"/>
<style name="activated" parent="AppTheme"/>
</resources>
Step #3: In your layout XML resource for the row in the ListView, add style="#style/activated" to the list of attributes of the root element
Step #4: Set the ListView to be a single-choice list, such as the following line in a ListFragment:
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
You can see this in action in this sample project, this sample project, and this sample project. For more background on those first two samples, see this SO question: Complete Working Sample of the Gmail Three-Fragment Animation Scenario?
Using
android.R.layout.simple_list_item_activated_1
instead of
R.layout.simple_list_item_checkable_1.
Just for somebody checking someday.
after days of search and pulling my hair i just found out that activatedBackgroundIndicator is also available in ActionBarSherlock styling system. Most of the devs which develop backwards compatible apps, use ActionBarSherlock,so using ActionBarSherlock is a good option for most cases. So instead of using android:background="?android:attr/activatedBackgroundIndicator" which will give errors in android versions prior to 11, just use: android:background="?activatedBackgroundIndicator"
here is the example row layout xml code:
<?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="wrap_content"
//note the activatedBackgroundIndicator
android:background="?activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:textSize="15sp" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingRight="5dip"
android:textSize="20dip" />
</LinearLayout>
Related
Apologies if this has already been answered, but I've been looking through answers/trying things for a couple of hours and I can't find anything.
I find the android spinner boxes too big:
For my taste, there is far too much grey space around the '80' and the '90' above. I'd like to make them less high and less wide.
However, I don't just want to set a pixel height/width, because of the lack of assurance that they'll look right on all devices.
They are set to wrap_content now. Is there any way to get it to wrap the content, but more tightly? There seems to be a fair amount of padding in there...
Many thanks!
EDIT:
I've made a little progress, I've figured out how to attach a style to a view, so now I am trying:
<Spinner
style="#style/spinner_style"
etc
and
<style name="spinner_style">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingLeft">0dp</item>
<item name="android:paddingRight">0dp</item>
<item name="android:paddingTop">0dp</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:layout_marginLeft">0dp</item>
<item name="android:layout_marginRight">0dp</item>
<item name="android:layout_marginTop">0dp</item>
<item name="android:layout_marginBottom">0dp</item>
</style>
However, this seems to have hardly any effect:
vs
before. How can I get the boxes really close to the text?
EDIT:
Bit more progress. This image seems to be the entire grey box plus drop down:
android:background="#android:drawable/btn_dropdown"
If I can find some way to make that smaller? Again, I have the challenge that I want it to wrap the text properly, so that I can be sure it will display well on all devices.
EDIT:
I think I'm going to use my own layout for the spinner, but in a way that wraps the text reliably - probably using a linear layout and setting the background color on that. I'll post back when I have the full code.
As you didn't share the a bit of your spinner, I will suggest some options that may help you:
if you are using android.R.layout.simple_spinner_dropdown_item as your spinner item layout (when it's closed)
ArrayAdapter<Integer> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_dropdown_item, myList);
Then change it to android.R.layout.simple_spinner_item, the later one has little padding than the first.
If that still adds some padding, you can add android:theme="#android:style/Theme.Holo.Light.NoActionBar" attribute to your spinner xml, although this will change the spinner arrow
Another option is to create a custom spinner item, similarly replace the system layout with your item when creating the adapter.
here's the item layout (just a new a layout with a TextView with wrap_content width/height)
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
OK this is what I have arrived at and it gives me this effect:
compared to what I get with the default Spinner which is:
I much prefer my version, but of course these things are subjective.
What I've done is to set my own layout and textview within the adapter (seems you can set both), so that my adapter-setting code looks like this:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.my_spinner_layout, R.id.dropdowntext, list);
adapter.setDropDownViewResource(R.layout.my_spinner_dropdown_layout);
spinner.setAdapter(adapter);
I was also obliged to create my own custom layout for the dropdown - R.layout.my_spinner_dropdown_layout above - because the spinner reuses the textview used for the unopened box when it draws the dropdown list, so the same textview needs to be available in both layouts.
I created two new xml layout files called my_spinner_layout.xml and my_spinner_dropdown_layout.xml
They look like this respectively:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutDisplayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:background="#DDDDDD"
android:gravity="center"
android:orientation="horizontal">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/dropdowntext"
style="#style/spinner_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
<ImageView
android:id="#+id/dropdownicon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:contentDescription="TODO"
android:src="#drawable/dropdown" />
</LinearLayout>
and
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/dropdowntext"
style="#style/spinner_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
Basically, I have replaced the default, which is TextView and a huge grey background image including a dropdown arrow, with a horizontal linear layout containing a TextView and a dropdown IMAGE, with a grey background.
Now the grey wraps to the content very nicely (I've added padding of 5dp).
Hope this helps someone, or if there's something wrong with it, perhaps someone will correct me.
I have really worked hard to find you the best solution for your problem but it seems to be no way to do so. The only way is to create a custom spinner as described in https://stackoverflow.com/a/37859442/11896005
Also, sorry if I was annoying just wanted to help you!
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.
Background
I'm adding a theme chooser of "Holo" and "Holo Light" (and maybe the dark action bar too) for my app "App Manager". For now I first try them out, via XML files.
The problem
I'm using the support library by Google and try out the themes, yet no matter what attributes and themes I use, the textViews' color on my listView have the wrong color.
The listView contains 2 TextViews that are defined as such:
<TextView
android:id="#+id/appLabelTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/isSystemAppImageView"
android:layout_toRightOf="#+id/appIconImageView"
android:ellipsize="marquee"
android:text="label"
android:textAppearance="?android:attr/textAppearanceLarge"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/appDescriptionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/appLabelTextView"
android:layout_below="#+id/appLabelTextView"
android:layout_toLeftOf="#+id/isSystemAppImageView"
android:ellipsize="marquee"
android:text="description"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
Theme.AppCompat.Light and Theme.AppCompat:
Same happens when I do it all programmatically, and when I use ActionBarSherlock library.
Here's the themes configurations I use (tried ActionBarSherlock this time, but the same occurs for the normal support library) :
<style name="BaseTheme" parent="#style/Theme.Sherlock.Light"></style>
<style name="AppTheme" parent="#style/BaseTheme">
<item name="android:listSeparatorTextViewStyle">#style/PreferenceListHeader</item>
<item name="android:windowBackground">#color/normal_window_background</item>
</style>
and the manifest:
<application
android:name="com.lb.app_manager.utils.App"
android:allowBackup="true"
android:description="#string/app_description"
android:hardwareAccelerated="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
The activity I've shown here doesn't have any code or XML that sets the theme to be different from what is written above.
What I've tried
I've tried to check out the samples and saw no apparent difference between the XMLs and code. They work just fine...
Also, for some reason, the preferences activities are shown just fine.
Same issue exists on ActionBarShelock library.
The question
How could it be ? what should be done to fix it?
I've found the cause to this problem.
It wasn't related to any XML or setting styles .
It was because of the LayourInflater of the adapter. I've created it via the application context instead of the one of the activity.
It also explains why my tests on sample projects worked fine, as I've checked the wrong stuff...
In Holo light theme and other Light themes we need to set Text color the only it will work..
<TextView
android:id="#+id/appLabelTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/isSystemAppImageView"
android:layout_toRightOf="#+id/appIconImageView"
android:ellipsize="marquee"
android:textcolor="#000"
android:text="label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/appDescriptionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/appLabelTextView"
android:layout_below="#+id/appLabelTextView"
android:layout_toLeftOf="#+id/isSystemAppImageView"
android:ellipsize="marquee"
android:textcolor="#000"
android:text="description"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
Hope this will work.. Try this and let me know the result.
I tried the sample you provided with Theme.AppCompat and Theme.AppCompat.Light, and they both work correctly as expected, on both API level 10 and 18. Since you didn't provide full code, only snippets, it must be the case that there are additional bits of XML or code in your application somewhere that cause the problem.
A couple of things for you to check:
Remove these entries from your AppTheme definition to make sure they are not interfering and causing the problem:
<item name="android:listSeparatorTextViewStyle">#style/PreferenceListHeader</item>
<item name="android:windowBackground">#color/normal_window_background</item>
You may have different style definitions for different API levels. Check the contents of res/values-v11/styles.xml, res/values-v14/styles.xml etc. to make sure they are not interfering
When doing web development, you can inspect an element and see which classes provide which css rules. Is there an equivalent for Android development?
TLDR; Here's an example of a style inheritance problem that I had and solved:
I had a dialog has the Holo theme, but the text color was dark, even when I tried to set the text color to white.
This is the dialog layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/Theme.Dialog"/>
</RelativeLayout>
In the style.xml resource:
<style name="Theme.Dialog" parent="android:style/Theme.Holo.Dialog">
<item name="android:windowTitleStyle">#android:style/TextAppearance.Large</item>
<item name="android:textColor">#color/solid_white</item>
<item name="android:windowNoTitle">true</item>
</style>
It turned out that I was using a Fragment whose Activity was a ListActivity, and it defined getView, which created the view from an xml style that set the text color to be dark. It would have liked to see what was setting the text color.
I agree with the comments on your question, but for future, if you want to get an idea of the view hierarchy (not styles) for your app - you can do so in Eclipse.
Run the app.
Window > Open Perspective > DDMS.
In the DDMS pane, click the icon to the left that looks like a stack of phones (next to the camera icon)
You can mouse around the screen and get a visual representation of the view hierarchy.
Might help in some way.
I've been searching the solution for hours: how to apply a simple theme or style to an application, an activity or just a view? It seems super easy but my styles always get ignored.
Here is the code in style.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="master" parent ="#android:style/Theme.NoTitleBar">
<item name="android:typeface">serif</item>
<item name="android:textColor">#8b8378</item>
</style>
</resources>
and here is the code in AndroidManifest.xml:
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#style/master">
and code in a ListView
<ListView android:layout_height="wrap_content"
style="#style/master"
android:id="#+id/list"
android:layout_width="fill_parent">
</ListView>
NOTHING ever happens. Font style, color all remain the default. Only by declare the attributes explicitly like
<TextView android:gravity="center" android:typeface="serif" android:textColor="#8b7d6b" android:textAppearance="?android:attr/textAppearanceSmall" android:id="#+id/text_intro" android:layout_height="wrap_content" android:text="#string/welcome_text" android:layout_width="wrap_content" android:padding="20sp" android:layout_weight="0"></TextView>
will work. I know eclipse doesn't support preview of theme and style, but they don't work on emulator as well.
Help please! I can't believe I have been stuck with this tiny issue for a week... Thank you in advance!
There are a few things about Android styles and resources at work here.
Android styles are an extremely general facility, and the result is that some configurations are possible but invalid and will be ignored. You've run across a few. :)
When applied to a view, a style will be equivalent to setting those same attributes on that view. Styles do not cascade to child views. typeface and textColor aren't valid on a ListView, so they are ignored. They also aren't going to work on a theme that way, since themes provide default styles for different kinds of views. (Why are invalid attributes silently ignored instead of generating an error? Because as new attributes are added in later platform revisions, older devices should ignore extra attributes that they don't know how to parse for compatibility.)
The best way to accomplish what you're trying to do is likely to be:
Create a style for TextViews. (This shouldn't have a parent that is a theme like your pasted code does.)
Apply that style to the TextView in your list item layout using the style= syntax.