Android NumberPicker: Set min, max, default from XML - android

Is there a way to set the minimum, maximum and default values of a NumberPicker from the XML Layout?
I'm doing it from within the Activity code:
np = (NumberPicker) findViewById(R.id.np);
np.setMaxValue(120);
np.setMinValue(0);
np.setValue(30);
XML is obviously more appropriate , because it defines property, not behaviour.
Is there a way to set these using the XML layout?

I had the same problem, this is how I solved it (according to the comment of MKJParekh):
I created my own NumberPicker-Class
package com.exaple.project;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.NumberPicker;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)//For backward-compability
public class MyNumberPicker extends NumberPicker {
public MyNumberPicker(Context context) {
super(context);
}
public MyNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
processAttributeSet(attrs);
}
public MyNumberPicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
processAttributeSet(attrs);
}
private void processAttributeSet(AttributeSet attrs) {
//This method reads the parameters given in the xml file and sets the properties according to it
this.setMinValue(attrs.getAttributeIntValue(null, "min", 0));
this.setMaxValue(attrs.getAttributeIntValue(null, "max", 0));
}
}
Now you can use this NumberPicker in your xml layout file
<com.exaple.project.myNumberPicker
android:id="#+id/numberPicker1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
max="100"
min="1" />
Thanks to MKJParekh for his useful comment

You can try this:
<NumberPicker
android:id="#+id/number_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:minValue="#{0}"
app:maxValue="#{120}"
app:value="#{30}"/>
This works as part of Android Databinding. So, you might want to set it to true in your app level build.gradle.
android {
...
dataBinding {
enabled true
}
}

Here is an updated version that follows the Android Docs
(and thus supports theming & Android Studio designer preview)
values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NumberPickerWithXml">
<attr name="maxValue" format="integer" />
<attr name="minValue" format="integer" />
<attr name="defaultValue" format="integer" />
</declare-styleable>
</resources>
NumberPickerWithXml.kt:
package com.example.library.ui
import android.content.Context
import android.util.AttributeSet
import android.widget.NumberPicker
import com.example.library.ui.R
class NumberPickerWithXml : NumberPicker {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
processXmlAttributes(attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
processXmlAttributes(attrs, defStyleAttr)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
processXmlAttributes(attrs, defStyleAttr, defStyleRes)
}
private fun processXmlAttributes(attrs: AttributeSet, defStyleAttr: Int = 0, defStyleRes: Int = 0) {
val attributes = context.theme.obtainStyledAttributes(attrs, R.styleable.NumberPickerWithXml, defStyleAttr, defStyleRes)
try {
this.minValue = attributes.getInt(R.styleable.NumberPickerWithXml_minValue, 0)
this.maxValue = attributes.getInt(R.styleable.NumberPickerWithXml_maxValue, 0)
this.value = attributes.getInt(R.styleable.NumberPickerWithXml_defaultValue, 0)
} finally {
attributes.recycle()
}
}
}
...or NumberPickerWithXml.java (untested):
package com.example.library.ui
import android.content.Context;
import android.util.AttributeSet;
import android.widget.NumberPicker;
import com.example.library.ui.R;
public class NumberPickerWithXml extends NumberPicker {
public NumberPickerWithXml(Context context) {
super(context);
}
public NumberPickerWithXml(Context context, AttributeSet attrs) {
super(context, attrs);
processXmlAttributes(attrs, 0, 0);
}
public NumberPickerWithXml(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
processXmlAttributes(attrs, defStyleAttr, 0);
}
public NumberPickerWithXml(Context context, AttributeSet attrs, int: defStyleAttr, int: defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
processXmlAttributes(attrs, defStyleAttr, defStyleRes);
}
private void processXmlAttributes(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
TypedArray attributes = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.NumberPickerWithXml, defStyleAttr, defStyleRes);
try {
this.setMinValue(attributes.getInt(R.styleable.NumberPickerWithXml_minValue, 0));
this.setMaxValue(attributes.getInt(R.styleable.NumberPickerWithXml_maxValue, 0));
this.setValue(attributes.getInt(R.styleable.NumberPickerWithXml_defaultValue, 0));
} finally {
attributes.recycle();
}
}
}
Usage in your layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<com.example.library.ui.NumberPickerWithXml
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:defaultValue="30"
custom:maxValue="120"
custom:minValue="0" />
</LinearLayout>

Related

Android: style not applied to a button

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>

View extending EditText loses Styles and is not focusable

I try to subclass EditText for convenience reasons (NumberEdit) using kotlin but the rendered View loses most of the EditText properties. The look is that of a TextView and it is not focusable with the mouse (in the emulator). When I click into the activity I can then edit the first of the NumberEdit widgets and can cycle to the next one with the tab key.
I added two emulator screenshots to illustrate the difference.
An EditText looks like this
The new NumberEdit looks like this
The extended class looks like this:
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.widget.EditText
class EditNumber(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int, defStyleRes: Int)
: EditText(context, attributeSet, defStyleAttr, defStyleRes) {
constructor(context: Context) : this(context, null, 0, 0)
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0, 0)
constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int)
: this(context, attributeSet, defStyleAttr, 0)
init {
inputType = InputType.TYPE_CLASS_NUMBER + InputType.TYPE_NUMBER_FLAG_DECIMAL
}
}
Does anyone have a clue what I am doing wrong? Do I have to reference some attributes explicitly?
I'm not a kotlin expert but if you look at the java source code for edittext you have following:
public class EditText extends TextView {
public EditText(Context context) {
this(context, null);
}
public EditText(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.editTextStyle);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
It doesn't look like you pass the right parameters to the constructor... You pass a lot of 0s and nulls...
In Kotlin you can write this much more concise:
class EditNumber #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = R.attr.editTextStyle,
defStyleRes: Int = 0
) : EditText(context, attrs, defStyle, defStyleRes)
Notice the defStyle parameter.

Not able to use custom LinearLayout giving xml inflate exception

I am facing one exception in my Custom Linear layout. Please see the sample code below.
public class ParentView extends LinearLayout {
private Menu mMenu;
public DontPressWithParentView(Context context, AttributeSet attrs, Menu menu) {
super(context, attrs);
mMenu = menu;
}
}
When I am using this layout in xml like below
com.android.ParentView
android:id="#+id/call_icon"
android:layout_width="91dip"
android:layout_height="83dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="22dip"
android:gravity="center" >
</com.android.hParentView>
It is giving me xml inflate exception. Please help me.
You have to implement the following constructors in your Viewcode:
public ParentView(Context context) {
super(context);
}
public ParentView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ParentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi (Build.VERSION_CODES.LOLLIPOP)
public ParentView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
Furthermore please check if your package declaration in your xml is correct:
com.android.ParentView
It sounds a bit weird to me.

Android create custom NumberPicker widget

I'm using some simvot number picker in application, I want to create custom widget for that and use in all of project, now i'm create this files but I can not set any value for custom widget.
My attributes:
<declare-styleable name="CNumberPicker">
<attr name="maxValue" format="string" />
<attr name="minValue" format="string" />
<attr name="value" format="string" />
</declare-styleable>
My Custom NumberPicker widget:
public class CNumberPicker extends net.simonvt.numberpicker.NumberPicker implements OnClickListener {
private int maxValue;
private int minValue;
private int value;
public CNumberPicker(Context context) {
super(context);
}
public CNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
processAttributeSet(attrs);
}
public CNumberPicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CNumberPicker, defStyle, 0);
processAttributeSet(attrs);
maxValue = Integer.parseInt(a.getString(R.styleable.CNumberPicker_maxValue));
minValue = Integer.parseInt(a.getString(R.styleable.CNumberPicker_minValue));
a.recycle();
setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
private void processAttributeSet(AttributeSet attrs) {
this.setMaxValue(attrs.getAttributeIntValue(null, "maxValue", 0));
}
}
My defined widget into xml:
<com.sample.widget.CNumberPicker
android:id="#+id/np_choose_hour"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_weight="0.20"
android:gravity="center_horizontal"
app:maxValue="10"
app:minValue="1"
app:value="5">
</com.sample.widget.CNumberPicker>
how to set value defined into xml in layout?
You have to inflate the layout in code.
public CNumberPicker(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.cnumberpicker, this);
}
presuming the layout file is cnumberpicker.xml
EDIT: These 3 functions are constructors. Any one of them could be called to construct the object. By using this instead of super we can force all constructors to end up calling the 3 parameter constructor. You need some cohesion here. You don't want to copy paste code every time you make one change.
public CNumberPicker(Context context) {
this(context, null);
}
public CNumberPicker(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CNumberPicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CNumberPicker, defStyle, 0);
processAttributeSet(attrs);
// this method allows a default value if no attributes are given. You should use them.
maxValue = Integer.parseInt(a.getString(R.styleable.CNumberPicker_maxValue,"10"));
minValue = Integer.parseInt(a.getString(R.styleable.CNumberPicker_minValue,"0"));
a.recycle();
}

Adding compound view class into view programatically in android

Hi I am trying to add compound view class into my view programmatically. But I don't know how to do that.
I can add directly it in to layout and thats working fine.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLlt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.androidcustomvliveapplication.widget.CustomCardSection
android:id="#+id/cardSection2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</com.example.androidcustomvliveapplication.widget.CustomCardSection>
</LinearLayout>
Above thing working fine. But I want to add above composite layout programmatically.
LIke I want to do like this
mainLlt.add(customcardsection)
Need Some help. Thank you.
public class CustomCardSection extends RelativeLayout
{
int section;
#SuppressLint("NewApi")
public CustomCardSection(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public CustomCardSection(Context context, AttributeSet attrs,
int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public CustomCardSection(Context context, AttributeSet attrs)
{
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.custom_card_section, this, true);
}
public CustomCardSection(Context context)
{
super(context);
}
}

Categories

Resources