I've found an improvement that may help not to hardcode view values into java classes in my android app. I wonder how can i get it to work. I want to to use this kind of view in my adapter (that means that i cannot use #style attribute in my layout's root). What am i doing wrong?
Code:
styles.xml:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="customViewStyleRef">#style/CustomViewStyle</item>
</style>
<attr name="customViewStyleRef" format="reference"/>
<style name="CustomViewStyle" parent="#android:style/Widget.TextView">
<item name="android:layout_margin">10dp</item>
</style>
</resources>
View class:
public class CustomView extends View {
public CustomView(Context context) {
super(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.customViewStyleRef);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, R.attr.customViewStyleRef);
}
public void init(#NonNull ViewGroup parentView) {
inflate(getContext(), R.layout.custom_view, parentView);
}
}
View layout:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f00"
android:textColor="#fff"
android:textSize="50sp"
android:text="test text"/>
</merge>
Problem: The TextView container does not have any padding that i specified in styles.xml (see the image).
You should initialize the TextView, then use the style for the TextView or you can solve this problem by putting style name inside the TextView and use an id for the TextView it will help for using it.
<TextView
android:id="#+id/custom_tv"
style="#style/CustomViewStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f00"
android:textColor="#fff"
android:textSize="50sp"
android:text="test text"/>
I think i've figured this out. My built files were somehow cached and i couldn't get it to work. And i took a wrong testing parameter. My approach worked 😁
Related
I'm trying to create custom view and set its style programatically. I created custom view based on AppCompatButton:
public class RangeSelectorButton extends androidx.appcompat.widget.AppCompatButton {
public int onClickKey = -1;
public RangeSelectorButton(Context context) {
this(context, null);
}
public RangeSelectorButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, R.style.RangeSelectorButton);
}
}
and now I get stuck in strange behaviour:
<ru.SomeDomain.CustomViews.RangeSelector
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true" android:focusable="true">
<!-- In this case all works fine -->
<ru.SomeDomain.RangeSelectorButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="10dp"
android:minWidth="40dp"
style="#style/RangeSelectorButton"
/>
<!-- Style not applies -->
<ru.SomeDomain.CustomViews.RangeSelectorButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="10dp"
android:minWidth="40dp"
/>
</ru.SomeDomain.CustomViews.RangeSelector>
What I should to do if I don't want use style attribute in xml every time when I create my custom view?
If it is necessary my style.xml contains:
<style name="RangeSelectorButton" parent="#android:style/Widget.Button">
<item name="android:background">#drawable/range_toggle_button_selector</item>
</style>
range_toggle_button_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/range_unselected" android:state_pressed="false" />
<item android:drawable="#drawable/range_selected" android:state_pressed="true" />
</selector>
The problem here is that you're passing a style in the place of the defStyleAttr parameter, which expects an attribute, not a style. There's two solutions here:
Use an attribute. In attrs.xml declare:
<attr name="rangeSelectorButtonStyle" format="reference"/>
and in your app theme:
<item name="rangeSelectorButtonStyle">#style/RangeSelectorButton</style>
and change your constructor to:
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.rangeSelectorButtonStyle);
}
If you're making a library for example, this is the best way of doing it since it allows users to customize your widget style.
If you don't want to use an attribute, you can call the fourth View constructor, which has a parameter that takes a default style and not an attribute:
View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
Add this constructor to your view and in the second constructor, call the fourth like this:
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, 0, R.style.RangeSelectorButton);
}
Note that the fourth constructor requires API 21.
I've noticed that the SwitchCompat's font does not seem to change with what I've set in the fontFamily field. I've also tried using styles with custom fontFamily (which works on TextViews) and even the switchTextAppearance field. It does apply on the preview (I know the preview is not really accurate) but not when I tried running it on my test device.
Here's my SwitchCompat:
<android.support.v7.widget.SwitchCompat
style="#style/MyStyle.Body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="#font/my_font_family"
android:text="Enable"
app:switchTextAppearance="#style/MyStyle.Body"/>
and here's my style:
<style name="MyStyle.Body" parent="Base.TextAppearance.AppCompat.Body1">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">#font/my_font_family</item>
<item name="android:textColor">#color/color_primary_text</item>
</style>
As you can see, I only really want to change it's font
EDIT
I've changed my style to this
<style name="MyStyle.Switch" parent="Widget.AppCompat.CompoundButton.Switch">
<item name="android:textSize">14sp</item>
<item name="android:textColor">#color/color_primary_text</item>
<item name="android:fontFamily">#font/my_font_family</item>
<item name="fontFamily">#font/my_font_family</item>
</style>
still doesn't work though
XML settings is not working, therefore I use following code:
someSwitch.setTypeface(ResourcesCompat.getFont(context, R.font.roboto));
Try
parent="Base.TextAppearance.AppCompat.Body1"
replace into this
parent="TextAppearance.AppCompat.Widget.Switch"
Try below
public class CustomSwitchCompact extends SwitchCompat {
public CustomSwitchCompact(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomSwitchCompact(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomSwitchCompact(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface myFonts = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Roboto_Bold.ttf");
setTypeface(myFonts);
}
}
}
XML file
<com.test.CustomSwitchCompact
android:id="#+id/switch_compat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:checked="false"
android:padding="20dp"
android:text="SwitchCompat"
android:textOff="OFF"
android:textOn="ON"
app:showText="true" />
Another way to achieve SwitchCompact with custom font
<android.support.v7.widget.SwitchCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/adamSwitch"
android:textColor="#color/top_color"
android:textAppearance="#color/top_color"
android:gravity="center"
app:showText="true"
android:fontFamily="#font/my_font_family"
app:theme="#style/Custom.Widget.SwitchCompat"
app:switchPadding="5dp"
/>
in style.xml
<style name="Custom.Widget.SwitchCompat" parent="Widget.AppCompat.CompoundButton.Switch" >
<item name="android:textColorPrimary">#color/blue</item>
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">#font/my_font_family</item>
<item name="android:textColor">#color/color_primary_text</item>
</style>
The only thing that works for me is setSwitchTypeface, not setTypeface:
my_switch.setSwitchTypeface(ResourcesCompat.getFont(context, R.font.my_font))
I've used android:textAppearance instead of android:switchTextAppearance and custom font works now. Also my switch style have Widget.AppCompat.CompoundButton.Switch as parent
I have an Android application which uses Material design theme with backward compatibility through AppCompat.
There are multiple Textview's and EditText's in my application. I would like the same properties to be applied to all these TextView's and EditText's across the application. In order to achieve this, i have defined a custom style as shown below:
<!-- Base application theme. -->
<style name="ParentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="ArabicTheme" parent="ParentTheme">
<item name="android:editTextStyle">#style/arabicEditText</item>
<item name="android:textViewStyle">#style/arabicTextView</item>
</style>
<style name="arabicEditText" parent="#android:style/Widget.EditText">
<item name="android:gravity">right</item>
<item name="android:ellipsize">end</item>
</style>
<style name="arabicTextView" parent="#android:style/Widget.TextView">
<item name="android:gravity">right</item>
</style>
In my AndroidManifest.xml file under the <Application> tag, i have set android:theme="#style/ArabicTheme".
Below is the output of the activity:
As seen in the above output, the Style is being applied to TextView only. However, The same is not being applied to EditText.
Incase, if i explicitly specify these properties to the EditText in the corresponding Actitivy's xml as shown below:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:hint="Name"
android:ellipsize="end"
android:gravity="right"
android:ems="10"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="16dp"
android:id="#+id/editText" />
i.e I have explicitly added android:ellipsize="end" and android:gravity="right" to the <EditText>, and only then the output is as expected:
Like i said, i have multiple TextView's and EditText's and i cannot explicitly add these properties to all of them. So, is there a way i can achieve this using Styles or any other approach? Am i doing something wrong here?
Your approach is correct. Just remove android: from the editText's attribute name:
<item name="editTextStyle">#style/arabicEditText</item>
I cannot explain this though. I guess appCompat things don't reuse android attributes, but add another ones with similiar names. Same goes with colorPrimary, srcCompat and others.
I have been doing this
public class LightEditText extends android.widget.EditText{
public LightEditText(Context context) {
super(context);
setFont();
}
public LightEditText(Context context, AttributeSet attrs) {
super(context, attrs);
setFont();
}
public LightEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setFont();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LightEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setFont();
}
/**
* This method is used to set the given font to the TextView.
*/
private void setFont() {
Typeface typeface = TypefaceCache.get(getContext().getAssets(), "fonts/Roboto-Light.ttf");
setTypeface(typeface);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
Then inside your xml file
<com.packagename.LightEditText
android:id="#+id/edtTaskName"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
Do the above method for setting common properties(fontType,style..etc) to editext
I am working on a project which was developed by another developer.To set icons he has used icon codes like this
<string name="icAddress">\ue902</string>
<string name="icAgeGroup">\ue903</string>
I generally use icons as as imageview but he has used it as customtextview like this
<com.util.CustomTextView
android:id="#+id/tvIcAddress"
style="#style/menuIcon"
android:text="#string/icAddress" />
style.xml
<style name="menuIcon">
<item name="android:layout_width">#dimen/dpSize50</item>
<item name="android:gravity">center</item>
<item name="android:textColor">#color/appColor</item>
<item name="android:layout_height">match_parent</item>
<item name="android:textSize">#dimen/bigTextSize</item>
</style>
The project has a font file in assets folder and in CustomTextView he has applied that font using setTypeface.I am not getting what's going on here.Now i want to use skype icon in some layout.How would i use it in same fashion.How can i get its icon code.
here is the CustomTextViewFile
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
applyCustomFont(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
applyCustomFont(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
applyCustomFont(context);
}
private void applyCustomFont(Context context) {
setTypeface(Util.getIns().getCustomFont(context));
}
}
getCustomFont method:
public Typeface getCustomFont(Context context) {
if (customTypeFace == null) {
customTypeFace = Typeface.createFromAsset(context.getAssets(), "hell.ttf");
return customTypeFace;
}
return customTypeFace;
}
Xml code of layout:
<LinearLayout
android:id="#+id/linearMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="#+id/linearHistory"
android:layout_width="match_parent"
android:layout_height="#dimen/dpSize45"
android:orientation="horizontal">
<com.util.CustomTextView
android:id="#+id/tvIcCaseHistory"
style="#style/menuIcon"
android:text="#string/icCaseHistory" />
<com.util.CustomTextView
android:id="#+id/tvCaseHistory"
style="#style/menuText"
android:text="Case History" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.25dp"
android:layout_marginLeft="#dimen/dpSize50"
android:layout_marginRight="#dimen/dpSize15"
android:background="#color/appColor" />
<LinearLayout
android:id="#+id/linearPrescription"
android:layout_width="match_parent"
android:layout_height="#dimen/dpSize45"
android:orientation="horizontal">
<com.util.CustomTextView
android:id="#+id/tvIcPrescription"
style="#style/menuIcon"
android:text="#string/icPrescription" />
<com.util.CustomTextView
android:id="#+id/tvPrescription"
style="#style/menuText"
android:text="Prescription" />
</LinearLayout>
</LinearLayout>
screenshot showing icons:
link
The values,
<string name="icAddress">\ue902</string>
<string name="icAgeGroup">\ue903</string>
are utf encoded characters, and to show that characters he used font in assets folder,
The corresponding character of any utf can be found;
Here
In your case the customtextview shows the specified character, there should be an image somewhere in your application that is being showed in the layout.
I want to have a line below a text view with a blue color I came across this post in this post having this as a one of the answer I tried it and is working fine but I want to change the color of the textview and the line below it.
just add this style:
style="?android:listSeparatorTextViewStyle"
to your TextView
I also have tried extracting the style but it is giving me error while inheriting the said style
My style is as follows
<style name="blueBoldText" parent="?android:listSeparatorTextViewStyle">
<item name="android:textColor">#color/DarkTurquoise</item>
<item name="android:textStyle">bold</item>
</style>
Actually, the value of the attribute
?android:listSeparatorTextViewStyle
is
#android:style/Widget.Holo.Light.TextView.ListSeparator
So you can inherit this style instead.
You can extend TextView and set listSeparatorTextViewStyle.
public class HeaderView extends TextView {
public HeaderView(Context context) {
super(context, null, android.R.attr.listSeparatorTextViewStyle);
}
public HeaderView(Context context,
AttributeSet attrs) {
super(context, attrs, android.R.attr.listSeparatorTextViewStyle);
}
}
then
<com.gmail.sikambr.alib.HeaderView
style="#style/your_style"
android:text="..."
android:layout_width="fill_parent"
android:layout_height="wrap_content" />