I'm trying to make my disabled EditText's style like in guidelines:
https://www.google.com/design/spec/components/text-fields.html#text-fields-labels
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/test_account"
android:enabled="false" />
I've already implemented material design styles, so all my widgets look material.
The question is: Is there any way to get this dotted underline using styles, without putting additional views?
My styles.xml:
<style name="Theme.Main" parent="#style/Theme.AppCompat.Light.NoActionBar">
<item name="android:editTextStyle">#style/android:Widget.Material.EditText</item>
</style>
Finally I managed to do as you've shown, It looks like
Create dotted.xml inside drawable folder and paste these
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape android:shape="rectangle">
<stroke
android:width="0.5dp"
android:color="#android:color/black" />
<solid android:color="#ffffff" />
<stroke
android:width="1dp"
android:color="#030310"
android:dashGap="5dp"
android:dashWidth="5dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
</item>
</layer-list>
Then simply set the android:background attribute to dotted.xml we just created. Your EditText looks like this.
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test account"
android:background="#drawable/dotted"
style="#style/Theme.Main" <!--Its your custom style-->
android:enabled="false" />
AFAIK, there is no "stock" way. Take the material design guidelines as it is, a guideline ;)
Finally I ended up with a custom view. It might be not the most elegant solution but it solves my task.
Hope it will be helpful for someone.
DisabledTextField.java:
package com.kabunov.example.ui.common;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.kabunov.example.R;
public final class DisabledTextField extends FrameLayout {
private TextView tvCaption;
private TextView tvText;
private View divider;
public DisabledTextField(final Context context) {
this(context, null);
}
public DisabledTextField(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DisabledTextField(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
View.inflate(getContext(), R.layout.component_disabled_text_field, this);
tvCaption = (TextView) findViewById(R.id.caption);
tvText = (TextView) findViewById(R.id.value);
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DisabledTextField);
if (null != typedArray) {
final String captionText = typedArray.getString(R.styleable.DisabledTextField_caption);
if (TextUtils.isEmpty(captionText)) {
tvCaption.setVisibility(GONE);
} else {
tvCaption.setText(captionText);
tvCaption.setVisibility(VISIBLE);
}
final String text = typedArray.getString(R.styleable.DisabledTextField_disabledText);
tvText.setText(text);
typedArray.recycle();
}
}
public final void setCaption(final CharSequence caption) {
this.tvCaption.setText(caption);
this.tvCaption.setVisibility(VISIBLE);
}
public final void setDisabledText(final CharSequence value) {
this.tvText.setText(value);
}
}
/layout/component_disabled_text.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">
<TextView
android:id="#+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldCaption"/>
<TextView
android:id="#+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldValue"/>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#drawable/disabled_text_field_background"
android:layerType="software"/>
</LinearLayout>
/values/attributes_disabled_text_field.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DisabledTextField">
<attr name="caption" format="string"/>
<attr name="disabledText" format="string"/>
</declare-styleable>
</resources>
/drawable/disabled_text_field_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-1dp"
android:left="-1dp"
android:right="-1dp"
android:top="0dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/text_color_disabled_text_view"
android:dashGap="2dp"
android:dashWidth="1dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
</layer-list>
/values/styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="text_color_disabled_text_view">#61000000</color>
<style name="DisabledTextFieldCaption">
<item name="android:textSize">12sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
<style name="DisabledTextFieldValue">
<item name="android:layout_marginTop">3dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
</resources>
Example of usage:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.kabunov.example.ui.common.DisabledTextField
android:id="#+id/example"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:caption="Some caption"
custom:disabledText="Disabled text"/>
</LinearLayout>
And the result:
Related
I need TextInputEditText bottom line color like below.
Default color => Gray
If user enter text, line color should remain as Blue. Currently, if i
enter input in first edittext and go to other edittext, first one
becoming gray again.
Edittext is Empty => Gray
I also require default hint animation of TextInputLayout, So, can't use EditText. I implemented this by using TextWatcher like here but not working.
Here is my code
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/EditScreenTextInputLayoutStyle"
app:hintTextAppearance="#style/etHintText">
<android.support.design.widget.TextInputEditText
android:id="#+id/etAddress"
style="#style/et_14_blk_sngl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:inputType="text"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
Style :
<style name="EditScreenTextInputLayoutStyle">
<item name="colorControlNormal">#color/gray</item>
<item name="colorControlActivated">#color/blue</item>
<item name="colorControlHighlight">#color/blue</item></style>
And,
private void UpdateLineColor()
{
if (!TextUtils.IsEmpty(this.Text))
{
DrawableCompat.SetTint(this.Background, ContextCompat.GetColor(this.Context, Resource.Color.blue));
if (Build.VERSION.SdkInt >= Build.VERSION_CODES.Lollipop)
{
ColorStateList colorStateList = ColorStateList.ValueOf(Resources.GetColor(Resource.Color.blue));
this.BackgroundTintList = colorStateList;
ViewCompat.SetBackgroundTintList(this, colorStateList);
}
this.Background.SetColorFilter(Resources.GetColor(Resource.Color.blue), PorterDuff.Mode.SrcAtop);
}
else
{
DrawableCompat.SetTint(this.Background, ContextCompat.GetColor(this.Context, Resource.Color.gray));
if (Build.VERSION.SdkInt >= Build.VERSION_CODES.Lollipop)
{
ColorStateList colorStateList = ColorStateList.ValueOf(Resources.GetColor(Resource.Color.gray));
this.BackgroundTintList = colorStateList;
ViewCompat.SetBackgroundTintList(this, colorStateList);
}
this.Background.SetColorFilter(Resources.GetColor(Resource.Color.gray), PorterDuff.Mode.SrcAtop);
}
}
you could custon the TextInputEditText's background,like this:
custom et_underline_selected.axml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape>
<solid android:color="#android:color/transparent" />
<stroke
android:width="1dp"
android:color="#00f" /> // color blue
<padding android:bottom="4dp" />
</shape>
</item>
</layer-list>
et_underline_unselected.axml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape>
<solid android:color="#android:color/transparent" />
<stroke
android:color="#0f0"
android:width="1dp" />
<padding android:bottom="4dp" />
</shape>
</item>
</layer-list>
edittext_bg_selector.axml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:drawable="#drawable/et_underline_unselected"/>
<item android:state_focused="false"
android:drawable="#drawable/et_underline_selected"/>
</selector>
these three files put in Resources/drawable
then in your layout.axml:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="#style/etHintText">
<android.support.design.widget.TextInputEditText
android:id="#+id/etAddress"
style="#style/et_14_blk_sngl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:inputType="text"
android:background="#drawable/edittext_bg_selector"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
finally in your activity.cs:
TextInputEditText etAddress = FindViewById<TextInputEditText>(Resource.Id.etAddress);
etAddress.FocusChange += (s, e) =>
{
if (e.HasFocus)
{
etAddress.SetBackgroundResource(Resource.Drawable.et_underline_selected);
}
else
{
if (etAddress.Text.Length > 0)
{
etAddress.SetBackgroundResource(Resource.Drawable.et_underline_selected);
}
else
{
etAddress.SetBackgroundResource(Resource.Drawable.et_underline_unselected);
}
}
};
is this effect you need ?
Replace your style with:
<style name="EditScreenTextInputLayoutStyle" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorControlNormal">#color/gray</item>
<item name="colorControlActivated">#color/blue</item>
<item name="colorControlHighlight">#color/blue</item>
</style>
I have one requirement to create shadow in TextView?
How can I achieve it? attached screensort.
If have any idea then let me know.
Thanks!!! in advance.
In your XML add elevation property. Set it to 5dp.
<TextView
android:id="#+id/myText"
...
android:elevation="5dp" />
On API>=21 you can directly use CustomViewOutlineProvider
CustomViewOutlineProvider.java
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class CustomViewOutlineProvider extends ViewOutlineProvider {
int roundCorner;
public CustomViewOutlineProvider(int round) {
roundCorner = round;
}
#Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), roundCorner);
}
}
Activity
TextView textView = (TextView) findViewById(R.id.shadow_txt);
textView.setOutlineProvider(new CustomViewOutlineProvider(30));
textView.setClipToOutline(true);
For Prelollipop Devices(API<21)
<TextView
android:background="#drawable/btn_with_shadow"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Font Style"
android:textColor="#color/white"
android:paddingRight="24dp"
android:paddingLeft="24dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
/>
btn_with_shadow.xml
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_shadow"/>
<item
android:drawable="#drawable/bg_button"
android:bottom="4px"
android:top="3px"
android:right="4px"
android:left="3px"/>
</layer-list>
btn_shadow.xml
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/alpha_15"/>
<corners android:radius="20dip"/>
</shape>
bg_button.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/colorPrimary"/>
<corners android:radius="20dp" />
</shape>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="alpha_15">#26000000</color>
</resources>
Result -
I have been trying to edit a FragmentedTabHost's background colors to mess around with it a bit and I am quite clueless as to why I can changed the "unselected" state but not the "selected" state.
So what I have is a main drawable called "tabs" and inside I have references to two others "tab_selected" and "tab_unselected". I applied this background pretty much everywhere I could find to see if it worked but I got to the point where I think the best place to put it is in the TabWidget tag.
The selected state remains with the grayish color of the normal tab but the other one actually changes.
I don't know if I should be changing code elsewhere, as I already changed in the code it self by saying:
mTabHost.setBackgroundResource(R.drawable.tabs);
And still no progress...
Below is the code:
tabs.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/tab_selected" />
<item android:state_selected="false"
android:drawable="#drawable/tab_unselected" />
</selector>
tab_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#7fff00" />
</shape>
</item>
<item android:top="20dp">
<shape android:shape="rectangle">
<solid android:color="#7fff00" />
</shape>
</item>
<item android:bottom="2dp">
<shape android:shape="rectangle">
<gradient android:startColor="#7fff00"
android:endColor="#7fff00"
android:angle="270" />
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
</shape>
</item>
</layer-list>
tab_unselected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#86B4CF" />
</shape>
</item>
<item android:top="20dp">
<shape android:shape="rectangle">
<solid android:color="#86B4CF" />
</shape>
</item>
<item android:bottom="2dp">
<shape android:shape="rectangle">
<gradient android:startColor="#86B4CF"
android:endColor="#6792AB"
android:angle="270" />
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
</shape>
</item>
</layer-list>
And finally the FragmentedHost:
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".Home"
android:orientation="vertical"
android:background="#drawable/global_background">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_date"
style="#style/header"/>
</LinearLayout>
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="#drawable/tabs"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
There is a method called setOnTabChangedListener. i hope this will help you
mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
setTabColor(mTabHost);
}
});
setTabColor(mTabHost) Function :
public static void setTabColor(TabHost tabhost) {
for (int i = 0; i < tabhost.getTabWidget().getChildCount(); i++) {
tabhost.getTabWidget().getChildAt(i)
.setBackgroundColor(Color.parseColor("#434a54")); // unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab())
.setBackgroundColor(Color.parseColor("#22262c")); // selected
}
Thank you both for your answers although I decided to go another way around.
As instead of using FragmentedTabHost I decided to use ActionBar Tab because it is the most recomended.
To do this I created this class:
public class ActionBarTabListener implements ActionBar.TabListener {
public Fragment fragment;
public ActionBarTabListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
//do what you want when tab is reselected, I do nothing
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_placeholder, fragment);
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
Changed my main class (the one holding all the tabs):
public class EntryDetails extends ActionBarActivity {
private Entry entry;
//private FragmentTabHost mTabHost;
private TextView tv_date;
private ActionBar ab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_entry_details);
ab = getSupportActionBar();
ab.setTitle("Ecz :: Entry Details");
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
entry = getIntent().getExtras().getParcelable("e");
/* TAB ITCHES */
Bundle i = new Bundle();
i.putParcelableArrayList("i", ArrayListHelper.OrderItchesByTime(entry.getItches()));
Fragment f = new TabItches();
f.setArguments(i);
ActionBar.Tab tab = ab.newTab().setText("Itches").setTabListener(new ActionBarTabListener(f)).setTag(i);
ab.addTab(tab);
/* TAB TREATMENTS */
i = new Bundle();
i.putParcelableArrayList("t", ArrayListHelper.OrderTreatmentsByTime(entry.getTreatments()));
f = new TabTreatments();
f.setArguments(i);
tab = ab.newTab().setText("Treatments").setTabListener(new ActionBarTabListener(f)).setTag(i);
ab.addTab(tab);
tv_date = (TextView) findViewById(R.id.tv_date);
tv_date.setText(entry.getDate());
}
}
Then I changed my XML in my EntryDetails.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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".Home"
android:orientation="vertical"
android:background="#drawable/global_background">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_date"
style="#style/header"/>
</LinearLayout>
<LinearLayout
android:id="#+id/fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
So now I only have the linearlayout and no more tabhost.
To give you more insight I place below the code to my TabItches:
public class TabItches extends ListFragment{
private ArrayList<Itch> itches;
public ListAdapter itchesAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.tab_layout_itches, container, false);
this.setRetainInstance(true);
itches = this.getArguments().getParcelableArrayList("i");
itchesAdapter = new ItchAdapter(getActivity(), itches);
setListAdapter(itchesAdapter);
return view;
}
}
To edit the appearance of my tabs now I had to do more things!
This code belongs in "#style"
<style name="Appy" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">#style/AppyActionBar</item>
<item name="actionBarStyle">#style/AppyActionBar</item>
<item name="android:actionBarTabStyle">#style/AppyActionBarTab</item>
<item name="actionBarTabStyle">#style/AppyActionBarTab</item>
</style>
<!-- ActionBar styles -->
<style name="AppyActionBar" parent="#style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">#color/AppyBlue</item>
<!-- Support library compatibility -->
<item name="background">#color/AppyBlue</item>
</style>
<style name="AppyActionBarTab" parent="#style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">#drawable/actionbar_tab_background</item>
<!-- Support library compatibility -->
<item name="background">#drawable/actionbar_tab_background</item>
<item name="android:gravity">center</item>
</style>
Only take into account "AppyActionBarTab" code bits please!
actionbar_tab_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="#color/AppyDeeperBlue"/>
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="#drawable/actionbar_tab_background_selected"/>
<item android:state_selected="true" android:state_pressed="true" android:drawable="#drawable/actionbar_tab_background_selected_pressed"/>
</selector>
actionbar_tab_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-5dp" android:left="-5dp" android:right="-5dp">
<shape android:shape="rectangle">
<stroke android:color="#color/AppyBlue" android:width="5dp"/>
<solid android:color="#color/AppyDeeperBlue"/>
</shape>
</item>
</layer-list>
actionbar_tab_selected_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-5dp" android:left="-5dp" android:right="-5dp">
<shape android:shape="rectangle">
<stroke android:color="#B8D0DE" android:width="5dp" />
<solid android:color="#color/AppyDeeperBlue"/>
</shape>
</item>
</layer-list>
I based my self on posts here all throughout StackOverFlow if I manage to find them again I will reference them.
Right now I am struggling with changing the divider's color in API 10 and I cannot seem to get around it! :D
I hope the answer is complete enough, if any problem just write and I will try to answer accordingly!!
EDIT
Fixed my problem with divider's color. What you need to do is change the divider's drawable.
action_tab_divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/AppyBlue" />
<stroke android:width="5dp"
android:color="#color/AppyBlue"/>
</shape>
and now you need to apply this to the style
<style name="Appy" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">#style/AppyActionBar</item>
<item name="actionBarStyle">#style/AppyActionBar</item>
<item name="android:actionBarTabStyle">#style/AppyActionBarTab</item>
<item name="actionBarTabStyle">#style/AppyActionBarTab</item>
<item name="android:actionBarDivider">#drawable/actionbar_tab_divider</item>
<item name="actionBarDivider">#drawable/actionbar_tab_divider</item>
</style>
Notice that we are overwriting in the "parent" style, not inside either of the two above!
Thank you for reading :)
I have a "complex" layout that I want to "move" to a custom component to be able to re-utilize easily but when I do that ProgressBar disappears. I think that the cause could be that the ProgressBar has a custom progressDrawable.
During code execution, progress bar is accessible and visible (well I can't see it, but I check that the visibility property is not the problem...) and there are no errors.
My Custom Layout
...
</LinearLayout>
</LinearLayout>
<!-- Progressbar -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="match_parent"
>
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="5dp"
android:id="#+id/progressBar"
android:progressDrawable="#drawable/customprogressbar"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
</LinearLayout>
My Custom Layout class
public class CustomLayout extends LinearLayout {
public CustomLayout(Context context) {
super(context);
}
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.custom_layout, this, true);
}
}
My progressDrawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Define the background properties like color etc -->
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#000001"
android:centerColor="#0b131e"
android:centerY="1.0"
android:endColor="#0d1522"
android:angle="270"
/>
</shape>
</item>
<!-- Define the progress properties like start color, end color etc -->
<item android:id="#android:id/progress">
<clip>
<shape>
<gradient
android:startColor="#007A00"
android:centerColor="#007A00"
android:centerY="1.0"
android:endColor="#06101d"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
My Container Layout Main Activity
<?xml version="1.0" encoding="utf-8"?>
<my.custom.namespace xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent">
</my.custom.namespace>
My Main Activity
...
setContentView(R.layout.main_activity);
...
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
// Progress bar is get fine, and I checked that visibility is VISIBLE
// I didn't change a line of code of this after moving the layout to a custom control
String showProgressbar = sharedPrefs.getString("settings_progressbar_value", Constants.PROGRESSBAR_VISIBLE_BY_DEFAULT);
if (showProgressbar.equals(Constants.PROGRESSBAR_VISIBLE_BY_DEFAULT)) {
mProgressBar.setVisibility(View.VISIBLE);
} else {
mProgressBar.setVisibility(View.GONE);
}
So I have a ListView and I want to change the color of each items background and text. This ListView is inside a ListFragment. My code inflates the layout in the onCreateView and inflates the layout of each item in the newView.
The android:state_pressed="true" is working fine, whenever I press in one item the background changes to that color. But when selecting an item neither the bg color or text color changes, even though I've defined an item with android:state_selected="true" in the selector.
Edit: I'm using SDK level 11 (Android 3.0) and a Motorola Xoom.
The list fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The list item layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="25dp"
android:background="#drawable/list_item_bg_selector">
<TextView android:id="#+id/form_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_xlarge"
android:textStyle="bold"
android:textColor="#drawable/list_item_text_selector" />
<TextView android:id="#+id/form_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_medium"
android:textStyle="normal"
android:layout_marginTop="5dp"
android:textColor="#drawable/list_item_text_selector" />
</LinearLayout>
The background 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/white" />
<item
android:state_selected="true"
android:drawable="#drawable/list_item_bg_selected" />
<item
android:drawable="#color/list_bg" />
</selector>
The text selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#color/white" />
<item
android:drawable="#color/list_text_blue" />
</selector>
The answer is to use the android:state_activated="true" state, instead of the "selected" state. More on this here: ListFragment Item Selected Background
The best solution with support of all API levels is to implement Checkable feature for list item View which means that the top view of your list item layout has to implement Checkable interface (in my case it was TextView, but the same can be applied on ViewGroup classes like LinearLayout). When you click on a list item, the ListView call setChecked method and there we change the state of View to use android:state_checked="true" selector. Together with list view android:choiceMode="singleChoice" it will select only one item.
The trick is to override onCreateDrawableState method and set the checked state here for drawables. See example of SelectableTextView bellow. After the setChecked is called, the checked state is stored and called refreshDrawableState.
Example of SelectableTextView:
package com.example.widget.SelectableTextView;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.TextView;
public class SelectableTextView extends TextView implements Checkable {
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
private boolean mChecked;
public SelectableTextView(Context context) {
super(context);
}
public SelectableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
setSelected(!mChecked);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
}
Example of selectable_list_item.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<com.example.widget.SelectableTextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/list_item_selector_foreground"
android:background="#drawable/list_item_selector_background"
tools:text="Item 1"/>
Example of list_item_selector_foreground.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- checked -->
<item android:color="#color/list_item_text_active" android:state_checked="true"/>
<item android:color="#color/list_item_text"/>
</selector>
Example of list_item_selector_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/list_item_background_selected" android:state_pressed="true"/>
<item android:drawable="#color/list_item_background_selected" android:state_focused="true"/>
<item android:drawable="#color/list_item_background_active" android:state_checked="true"/>
<item android:drawable="#color/list_item_background"/>
</selector>
Do not forget to set clickable="true" for the layout. This solved my problem.
List item layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_item_bg_selector"
android:clickable="true" >
<TextView
android:id="#+id/tvNewsPreviewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
android:textSize="#dimen/news_preview_title_textsize"
android:textStyle="bold" />
</RelativeLayout>
Background selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/black" />
<gradient android:startColor="#color/white" android:endColor="#color/white" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/holo_gray_darker" />
<gradient android:startColor="#color/holo_gray_bright" android:endColor="#color/holo_gray_bright" />
</shape>
</item>
</selector>
#Andrew S: Along with using activated state in selector , activated state must be set to false for default case as shown in below selector code.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
android:state_activated="false"
android:color="#color/dark_text_blue"/>
<item android:state_pressed="true"
android:color="#color/red"/>
<item android:state_activated="true"
android:color="#color/red"/>
</selector>