In styles.xml I got:
<style name="MyButtonStyle">
<item name="android:buttonStyle">#style/Base.Widget.AppCompat.Button.Borderless</item>
<item name="android:textSize">24px</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:textColor">#color/menuButtonForecolor</item>
<item name="android:textStyle">bold</item>
</style>
I wanna use this style inside CMyButton.java like this
public class CMyButton extends AppCompatButton {
private static int getDefStyleId()
{
return R.style.MyButtonStyle;
}
protected void initThis() {
}
public CMyButton(Context context) {
this(context,null, getDefStyleId());
}
public CMyButton(Context context, AttributeSet attrs) {
this(context, attrs, getDefStyleId());
}
public CMyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initThis();
}
}
I use this button in panel_layout.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/LinearLayoutTheme">
<college.test.progs.CMyButton
android:id="#+id/showFacultiesButton"
android:text="#string/faculties_button_title"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
And this panel_layout.xml is used inside CPanel.java
public class CPanel extends LinearLayout {
private CMyButton facultiesButton;
protected void initThis(Context context) {
inflate(getContext(),R.layout.panel_layout,this);
this.facultiesButton = (CMyButton) findViewById(R.id.showFacultiesButton);
}
public CPanel(Context context) {
this(context,null);
}
public CPanel(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CPanel(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initThis(context);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CPanel(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.initThis(context);
}
}
Then I add this panel layout to main activity's layout
But when I add this button to any activity the style is not applied. What is wrong with this class? I know that I can apply the style in layout file but I need to do it in the code
Did you change MyButtonStyle as your theme's android:buttonStyle attribute value?
Hope this helps!
There are 2 ways to apply a style to a view:
Apply it directly to the view:
<college.test.progs.CMyButton
android:id="#+id/showFacultiesButton"
android:text="#string/faculties_button_title"
android:gravity="center"
android:style="#style/MyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Apply it to the Application through the style.xml file:
<item name="buttonStyle">#style/MyButtonStyle</item>
Related
I want to implement a custom ImageView with some predefined attributes based on the xml file. To do that I prepared a layout wrapped within merge tag:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="#+id/my_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:src="#drawable/icon" />
</merge>
And extended ImageView class:
public class CustomImageView extends LinearLayout{
public ImageFormField(Context context) {
super(context);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ImageFormField(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
View.inflate(getContext(), R.layout.custom_image_view, this);
}
}
It works so far, but I actually don't need that LinearLayout as I could extend directly from the ImageView. By extending ImageView I'd like to have the possibility to override src parameter from the default layout.
So I removed merge tag to have only ImageView in the layout and tried this:
public class CustomImageView extends AppCompatImageView{
public ImageFormField(Context context) {
super(context);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageFormField(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
View.inflate(getContext(), R.layout.custom_image_view, null); //can't pass root here
}
}
... but the image is simply not displayed. I want to be able to use my view this way:
<com.my.package.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
with possibility to override src attribute. Is there a way to do that by inflating layout or do I have to go deep with attributes (including custom ones)?
UPDATE
By "overriding src attribute I mean that by default image will have source from its xml file, but user can use it that way to pass another value within this custom view:
<com.my.package.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/another_icon" />
To provide a "default" image but also allow the user to override that default by specifying the android:src attribute, you can do this:
package com.example.stackoverflow;
import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
public class CustomImageView extends AppCompatImageView {
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
if (getDrawable() == null) {
setImageResource(R.drawable.default_image);
}
}
}
Then you can use it like this:
<!-- will display `default_image` -->
<com.example.stackoverflow.CustomImageView
android:layout_width="200dp"
android:layout_height="200dp"/>
Or:
<!-- will display `other_image` -->
<com.example.stackoverflow.CustomImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="#drawable/other_image"/>
There's no need to inflate anything inside the custom image view, and no need to create custom attributes (though you could certainly create custom attributes and use them if you wanted to).
You could update the Java code to apply other "default" styles too.
i created simple widget as custom checkBox as this below code, in this code setting custom font work fine but i can't check or uncheck CheckBox
public class CustomFontCheckBox extends AppCompatCheckBox {
public CustomFontCheckBox(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setTypeface(FontManager.getInstance(getContext()).loadFont("fonts/my_font.ttf"));
}
public CustomFontCheckBox(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
#SuppressWarnings("unused")
private void internalInit(Context context, AttributeSet attrs) {
}
}
xml layout:
<com.myapp.test.Widgets.CustomFontCheckBox
android:id="#+id/ch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/sickness_depth_marginRight"
android:button="#null"
android:buttonTint="#color/colorAccent"
android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
android:text="#string/diabetes"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/body_text_color"/>
Well I think you are messing with its constructor and its style use it like this
public class CustomFontCheckBox extends AppCompatCheckBox {
public CustomFontCheckBox(Context context) {
super(context);
init();
}
public CustomFontCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomFontCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
//set your typeface here.
// setTypeface("");
}
}
I tried with THIS LINK to change the typeface of all preferences of PreferenceScreen.
It was changed everywhere except summary of ListPreference.
Can anyone has an idea how to apply custom font on summary of ListPreference?
UPDATE
I want to apply my custom font exist on assets folder, not the in-build one. Also android:textAppearanceListItemSecondary required API 21, my app support minimum API 15.
Finally the way to change the font for summary of ListPreference.
Override the onBindViewHolder method of ListPreference to set your custom typeface. Check below custom class.
public class CustomListPreference extends ListPreference {
private String typefaceTitle, typefaceSummary;
public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomListPreference(Context context) {
super(context);
}
#Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
if(!TextUtils.isEmpty(typefaceTitle)) {
TextView titleView = (TextView) holder.findViewById(android.R.id.title);
titleView.setTypeface(FontManager.getInstance().getFont(typefaceTitle));
}
if(!TextUtils.isEmpty(typefaceSummary)){
final TextView summaryView = (TextView) holder.findViewById(
android.R.id.summary);
summaryView.setTypeface(FontManager.getInstance().getFont(typefaceSummary));
}
}
private void init(Context context, AttributeSet attrs){
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Preference);
typefaceTitle = a.getString(R.styleable.Preference_typefaceTitle);
typefaceSummary = a.getString(R.styleable.Preference_typefaceSummary);
a.recycle();
}}
attrs.xml
<declare-styleable name="Preference">
<attr name="typefaceTitle" format="string"></attr>
<attr name="typefaceSummary" format="string"></attr>
</declare-styleable>
Usage in Preference screen.
<YOUR_CustomListPreference_PACKAGE_NAME.CustomListPreference
android:defaultValue="X"
android:dialogTitle="Dialog Title"
android:entries="#array/list_item_title"
android:entryValues="#array/list_item_value"
android:key="pref_list"
android:summary="%s"
android:title="#string/Preference Title"
app:typefaceTitle="YOUR FONT NAME"
app:typefaceSummary="YOUR FONT NAME"/>
Hope this help for other.
try this
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:textAppearanceListItemSecondary">#style/textAppearanceListItemSecondaryCustom</item>
</style>
<style name="textAppearanceListItemSecondaryCustom">
<item name="android:textSize">14sp</item>
<item name="android:typeface">monospace</item>
</style>
What is correct way to extend EditText?
The problem is following:
I have empty application from template with two EditText:
<?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">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="one"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="two"/>
</LinearLayout>
It works fine:
Then I create my custom view from EditText:
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
this(context, null);
}
public CuteEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CuteEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// some special initialization will be here
}
}
And when I change EditText to my CuteEditText, interface works incorrectly:
The problem is not only with view ot UI. If I type something in first EditText and than touch the second one, nohing happens: input will continue in first.
The same behaviour if I inherite CuteEditText from AppCompatEditText.
What is wrong?
Sources for experiment are available at https://github.com/tseglevskiy/EditTextExperiment
Your construtors are broken. This is how it should look:
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
super(context);
}
public CuteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CuteEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
You don't need the third constructor overload. The first one is for creating the view programmatically and the second one is for creating the view from xml. Those two should be enough for most cases.
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
this(context, null);
}
public CuteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
I try to align spinner and edit text by baseline, but it doesn't work:
It start happen after update support library dependency from 24.1.1 to 24.2.1 (support-v4, appcompat-v7, design).
This is my xml code:
<RelativeLayout
android:id="#+id/email_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spinner"
style="#style/MailSpinner"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:dropDownWidth="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="#+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_alignBaseline="#id/spinner"
android:layout_toStartOf="#id/spinner"
android:baselineAlignedChildIndex="0">
<android.support.v7.widget.AppCompatEditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="E-mail"
android:ellipsize="end"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:textSize="16sp"/>
</android.support.design.widget.TextInputLayout>
</RelativeLayout>
MailSpinner style:
<style name="MailSpinner" parent="Widget.AppCompat.Spinner.Underlined">
<item name="android:background">#drawable/spinner_textfield_background</item>
<item name="backgroundTint">#color/spinner_tint</item>
<item name="backgroundTintMode">src_atop</item>
</style>
Essentially the TextInputLayout isn't providing a baseline value to it's parent. We need to pipe the correct baseline of the EditText by extending TextInputLayout. This works for me, however, I'm not sure if the baseline would change due to other events from the TextInputLayout.
public class CTextInputLayout extends TextInputLayout {
public CTextInputLayout(Context context) {
super(context);
}
public CTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline()
{
EditText editText = getEditText();
return editText.getPaddingTop() + editText.getBaseline();
}
}
I think this version is better when hint label is floating
public class CTextInputLayout extends TextInputLayout {
public CTextInputLayout(Context context) {
super(context);
}
public CTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline() {
EditText editText = getEditText();
return getMeasuredHeight() - (editText.getMeasuredHeight() - editText.getBaseline());
}
}
Here's a version which aligns correctly when the TextInputLayout error text is set:
public class BaselineTextInputLayout extends TextInputLayout {
public BaselineTextInputLayout(Context context) {
super(context);
}
public BaselineTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BaselineTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline() {
EditText editText = getEditText();
if (editText == null) { return 0; }
return editText.getTop() + editText.getBaseline();
}
}