I experience strange situation: when I put check box by code, it has diffrent style then check box added by xml file.
this is the dynamically adding the check boxes:
LinearLayout checkboxGroup = (LinearLayout) v.findViewById(R.id.category_checkbox_group);
for(String category : categories) {
CheckBox checkBox = new CheckBox(getActivity());
checkBox.setText("dynamically added");
checkBox.setOnClickListener(mCategoryChecked);
checkboxGroup.addView(checkBox);
}
fragment of xml:
<LinearLayout
android:id="#+id/category_checkbox_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="xml added" />
</LinearLayout>
So after all I have one checkbox form xml and few checkboxes from code.
The screen looks like below:
so my questions are:
what style is default for dynamic views?
how to apply this style to xml's views?
is a easy way to change box in check box?
The style for the dynamically added view depends on the context. In your situation the context is your activity, so the style of the added view is the style of your activity. If you didn't setup a theme for your activity, then it is the theme of your application, that you defined in your styles.xml. Example:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
You most probably inflated the xml layout from a different context. If you are inflating it from the same context like your added views, the views should have the same style. Try to check this.
You can also set a style for one view in xml like that:
<View
style="#style/Example" />
Related
I am trying to create a view pragmatically and then add it to my activity. This bit is working fine, however the theme for the view group isn't inherited by my new view
My theme:
<style name="CustomButtonTheme" parent="#style/Widget.AppCompat.Button">
<item name="android:textColor">#FF0000</item>
<item name="android:background">#00FF00</item>
</style>
My layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/buttonArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:theme="#style/CustomButtonTheme">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This button inherits CustomButtonTheme" />
</LinearLayout>
Java code
AppCompatButton button = new AppCompatButton(getContext());
button.setText("This button does not inherit CustomButtonTheme");
LinearLayout buttonArea = findViewById<LinearLayout>(R.id.buttonArea);
buttonArea.addView(button);
An android:theme attribute in a layout will only have effect during inflation, and only on that particular subtree. It won't be applied to the Activity's overall theme.
All that attribute does, though, is cause the LayoutInflater to wrap its current Context with the specified theme in a ContextThemeWrapper. We could do something similar ourselves, and just to illustrate the basic usage:
ContextThemeWrapper wrapper = new ContextThemeWrapper(getContext(), R.style.CustomButtonTheme);
AppCompatButton button = new AppCompatButton(wrapper);
However, this has already been done for us, basically, when the LayoutInflater created a ContextThemeWrapper internally, for that android:theme attribute. That ContextThemeWrapper is the Context that the LinearLayout will have been created with, so we can simply use its Context to instantiate our AppCompatButton:
AppCompatButton button = new AppCompatButton(buttonArea.getContext());
As the OP points out, this has the added benefit of working in pretty much every similar setup without having to know the exact theme needed.
How do I "cascade" the value of a custom attribute from a parent view to its child view?
This is easiest to explain using an example:
<com.example.CustomLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:percent="35" >
<com.example.CustomView
android:id="#+id/customView1"
app:percent="how-to-get-app:percent-value-here???"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.example.CustomLayout>
Here, CustomLayout extends LinearLayout. I have defined a custom attribute "percent" in attrs.xml using <declare-styleable> element. As you can see, I set percent to 35 in the XML for CustomLayout.
I now want to pass in the same value to CustomView (which extends View) and which I will include in CustomLayout. I am unable to find a way to do this in XML (it is easy to do this in code though).
I tried the following:
app:percent="#attr/percent"
app:percent="?attr/percent"
Both of these (expectedly) fail with NumberFormatException at TypedArray#getInt().
So, any ideas on how to get this to work?
Although the idea comes a bit late and the method is not straight forward, I think it's still worth sharing. We can put custom attributes into a theme, so the attributes can be passed to all child views from the parent view where the theme is used (i.e., the attributes exist within the View Group).
Example as follows:
<integer name="percentage">35</integer>
<style name="CustomTheme" parent="suitable theme for your case">
<item name="percent">#integer/percentage</item>
</style>
<com.example.CustomLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:theme="#style/CustomTheme" >
<com.example.CustomView
android:id="#+id/customView1"
app:percent="?attr/percent" <!--Note: that's how it refers to the value,
however, re-assign the attribute value here is meaningless as attribute percent
should exist in all child views now. You can retrieve its value via
Theme.obtainStyledAttributes(R.style.CustomTheme, new int[] {R.attr.percent})
in every child view-->
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.example.CustomLayout>
I am struggling around with this problem for quite a long time. I searched for solutions and there were actually some suggestions for related problems, but nothing really worked correctly for me. So let's say I want to create an AlertDialog with a (long) message, a checkbox and two buttons.
// create dialog
AlertDialog.Builder dlg = new AlertDialog.Builder(this);
dlg.setTitle(R.string.dlg_title);
dlg.setMessage(R.string.dlg_msg);
// add checkbox
final CheckBox checkbox = new CheckBox(this);
dlg.setView(checkbox);
// add buttons
dlg.setPositiveButton(...);
dlg.setNegativeButton(...);
// show dialog
dlg.show();
This won't work, because if the dialog message becomes too long, the checkbox will not be completely shown. Additionally, it is going to be completely hidden in landscape mode.
Next try would be to lookup the original dialog layout file (for me it is located under android-sdk-linux_86/platforms/android-17/data/res/layout/alert_dialog.xml) and attempt to copy the relevant part to create our own "clone" of the inner dialog layout, just like this:
dialog_checkbox.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:overScrollMode="ifContentScrolls"
android:paddingBottom="12dip"
android:paddingLeft="14dip"
android:paddingRight="10dip"
android:paddingTop="2dip" >
<TextView
android:id="#+id/message"
style="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dip" />
</ScrollView>
<CheckBox
android:id="#+id/checkbox"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
We could try to add this view to our dialog like this:
// create dialog
AlertDialog.Builder dlg = new AlertDialog.Builder(this);
dlg.setTitle(R.string.dlg_title);
// add checkbox
LinearLayout checkboxLayout = (LinearLayout) View.inflate(mContext, R.layout.dialog_checkbox, null);
((TextView) checkboxLayout.findViewById(R.id.message)).setText(R.string.dlg_msg);
mCheckbox = (CheckBox) checkboxLayout.findViewById(R.id.checkbox);
mCheckbox.setText(R.string.dlg_checkbox_msg);
setView(checkboxLayout);
// add buttons
dlg.setPositiveButton(...);
dlg.setNegativeButton(...);
// show dialog
dlg.show();
This actually works quite well. Almost. We will not see any problem until we use Theme.Light for our app. But as soon as we use Theme.Light, the dialog text colors will become black and unreadable on the dark background. WHY?!
We've cloned the original Android alert dialog xml layout source code. But although we use attr/textAppearanceMedium as a text style, the text color becomes black under Theme.Light anyway.
If we use Theme.Light and create a "normal" dialog with a normal message via setMessage, the text color is white and readable.
What's wrong? How to solve this? I don't want to programmatically set the text color to white or black, this will not look good on custom user themes. Any suggestions?
I had the same problem and solved it by creating a ContextThemeWrapper for my desired Dialog Theme and used this when creating the AlertDialog Builder and when inflating the View to attach:
ContextThemeWrapper wrapper = new ContextThemeWrapper(this, R.style.DialogBaseTheme);
AlertDialog.Builder builder = new AlertDialog.Builder(wrapper);
View view = LayoutInflater.from(wrapper).inflate(R.layout.create_warning, null);
builder.setView(view);
The style R.style.DialogBaseTheme is defined in "/values/styles.xml" for Gingerbread and below as:
<style name="DialogBaseTheme" parent="android:Theme.Dialog"/>
Then it is also defined in "/values-v11/styles.xml" for Honeycomb and upward to use the Holo theme as:
<style name="DialogBaseTheme" parent="android:Theme.Holo.Light.Dialog" />
So on Gingerbread my custom View's TextViews are automatically coloured white and Honeycomb+ they are automatically coloured black for Holo Light.
I THINK I finally found out how to solve it. On the basis of my initial code, this seems to solve my problem:
// add checkbox layout
LinearLayout checkboxLayout = (LinearLayout) View.inflate(new ContextThemeWrapper(context, android.R.style.Theme_Dialog), R.layout.dialog_checkbox, null);
((TextView) checkboxLayout.findViewById(R.id.message)).setText(DIALOG_TEXT);
mCheckbox = (CheckBox) checkboxLayout.findViewById(R.id.checkbox);
mCheckbox.setText(CHECKBOX_NOT_AGAIN);
setView(checkboxLayout);
Note the ContextThemeWrapper. It makes that the dialog theme is assigned to the inflated layout. I hope, this finally solves that problem for the future.
Just inside textview add one attribute:
android:textColor="#color/white"
and define white color inside colors.xml which is inside res/values folder
<color name="white">#ffffff</color>
Or you may add directly
android:textColor="#fffff"(though not recommended.Above method is recommended.)
You can apply a custom style with a shadow to make your text visible whatever the text color is:
<resources>
<style name="Text.Shaded.Medium" parent="#android:attr/textAppearanceMedium">
<item name="#android:paddingLeft">4dp</item>
<item name="#android:paddingBottom">4dp</item>
<item name="#android:textColor">#FFFFFFFF</item>
<item name="#android:shadowColor">#000000</item>
<item name="#android:shadowDx">2</item>
<item name="#android:shadowDy">2</item>
<item name="#android:shadowRadius">2</item>
</style>
</resources>
However if it isn't visible enough for you you can apply an inner shadow, but unfortunately Android doesn't have a property for that so you'll have to use something like MagicTextView (mentioned by ABentSpoon in this question: Is there a way to add inner shadow to a TextView on Android?).
How to change style of second level list of ExpandableListView? For example, add background color or header\footer view.
Note, that I don't need to set background to each child. I need to set style for a whole second level.
Here is an example of what I'm trying to achieve (brown layout - is second level list):
As I said, I don't need to apply style for each item individually. Because I have a repeatable image at background (not just color). I know how apply styles and how to set it to each child view, but this is not what I can use to achieve such background.
EDIT
What I'm trying to achieve:
add shadow at the top of "At the cafe". It can be done easily with ListView, but how to get ListView in such case? Is there any ListView at all?
set repeatable image as a background of second level list (not for each child view individually).
One way this can be achieved is with the following.
Create a style xml in your res/values/ directory.
Now define your style however you want it. When used this way it will change all the Views where the style is applied to this particular style.
Here is my example i tested with:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="backgroundTest" parent="#android:style/TextAppearance.Medium">
<item name="android:background">#00FF00</item>
</style>
</resources>
Now add the style to your top level layout in the xml that defines the children for your ExpandableListView. For example, here is my child (note the style in my LinearLayout):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/backgroundTest"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/rightSideTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="25dp"
android:paddingLeft="50dp"
android:paddingTop="25dp" />
</LinearLayout>
This should change the color of all your children to green, i believe. You can change the style to whatever you want. There is some great documentation that i linked that should help you out.
I have spinner with a style selection (I set the spinner style in strings.xml) and it's works well if I set the style in main.xml. But I want to know how to set the style programmatically in which the style already defined in strings.xml.
Refer my code below
main.xml:
<Spinner
android:id="#+id/PassengersSpinner1"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_span="3"
android:layout_marginTop="6dp"
style="#style/SpinnerStyle" />
strings.xml:
<style
name="SpinnerStyle"
parent="#android:style/Widget.Spinner">
<item name="android:background">#android:drawable/btn_default</item>
</style>
Now, I want to know that how can I set this strings.xml programmatically without main.xml?
From all my reading, you cannot do it, because the style has to be set before the view is created.
You can do it if you create the view in code (since then you can set the style before creating the view).
If you want to do that, a good example is here. Both the question and the answer give you methods to achieve your goal.