Implement a RadioButtonPreference in Android - android

How can you implement a RadioButtonPreference in android? Just like the CheckBoxPreference.
Are there any workarounds?

Use a ListPreference. You need to have more than one radio button for it to be meaningful (otherwise, it would just be a checkbox).
If, for some reason, you do not want to use a ListPreference, grab the source code to CheckBoxPreference from the Android open source tree and roll your own Preference implementation. You should then be able to list your custom implementation in preference XML using the namespace (e.g., com.foo.RadioButtonPreference).

You can use a custom class extending from CheckBoxPreference like this:
public class RadioButtonPreference extends CheckBoxPreference {
public RadioButtonPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
}
public RadioButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
}
public RadioButtonPreference(Context context) {
this(context, null);
}
#Override
public void onClick() {
if (this.isChecked()) {
return;
}
super.onClick();
}
}
Then create a preference_widget_radiobutton.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
inside android.R.layout.preference. -->
<RadioButton android:id="#+android:id/checkbox"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="false"
android:focusable="false"/>

Related

Android custom attributes with data binding

I have a big library of custom components that I want to use in my Android app.
All components use custom attributes to customize its content.
This is a sample component declared in a XML file:
<myapp.CustomTextView
android:id="#+id/text_view_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginBottom="8dp"
custom:textContent="This is my text" />
This is the custom attributed declared:
<declare-styleable name="CustomTextView">
<attr name="textContent" format="string" />
</declare-styleable>
And this is the implementation of the custom component:
public class CustomTextView extends TextView {
private Context context;
public CustomTextView(Context context) {
this(context, null);
}
public CustomTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
readAttrs(context, attrs);
}
private void readAttrs(Context context, AttributeSet attrs) {
TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTextView,0, 0);
try {
String content = array.getString(R.styleable.CustomTextView_textContent);
initContent(context, content);
} finally {
array.recycle();
}
}
private void initContent(Context context, String content) {
...
}
}
The problem is that I'm using data binding in my app, so if I do this, the app doesn't compile:
<myapp.CustomTextView
android:id="#+id/text_view_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginBottom="8dp"
custom:textContent="#{mainView.content}" />
After reading a lot, the solution seems to be to create a bindingadapter for that custom attribute, but in my case, create a binding adapter for every custom attribute would be a huge work because there are tons of components and attributes.
Is there a way to reduce this amount of work or to adapt data binding to these custom attributes?

Android: best way to control view that added dynamically?

As the title, i want to know if there is a the best way to control a view that added dynamically. (we have to keep reference to the view that was added)
Some time, for a complex request we have to add view in runtime. The is some ways to do that. In my case:
Some time i use a listview/recyclerview and control view via the list/recycleview adapter.
Other way is use a hashmap.
Do you have any other ideas? and how it work?
I prefer way, when I define View both by Java and XML file. View created like this, gives you ability to call your own Java methods, but you don`t need to create whole layout dynamically in Java. Little example:
MyView.java:
public class MyView extends LinearLayout {
TextView textView;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init() {
inflate(getContext(), R.layout.my_view, this);
setOrientation(VERTICAL);
textView = (TextView) findViewById(R.id.text_view);
}
public MyView setContent(String value) {
textView.setText(value);
return this;
}
}
my_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</merge>
After that, you can simply add it in you layout through Java:
cont.addView(new MyView(this).setContent("Value"));
or xml:
<com.path.to.your.view.MyView
android:id="#+id/my_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

BitmapDrawable cannot be cast to RoundRectDrawableWithShadow

I am trying to extend a cardview to set the background image. I know that this can not be done with normal cardview. I have searched net and found plenty of solutions for setting a background color to the card view but none for image.
My code to do so:
public class CCView extends CardView {
public CCView (Context context) {
super(context);
init();
}
public CCView (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CCView (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setBackground(getResources().getDrawable(R.drawable.cc_background));
}
}
I get this exception when I populate the code from XML
android.graphics.drawable.BitmapDrawable cannot be cast to android.support.v7.widget.RoundRectDrawableWithShadow
Any solution?
As CardView extends FrameLayout you can layer layouts on top of it. To get around the problem you're having, I'd try adding a blank view "underneath" all the other elements in your view, and then set that view to inherit the state of its parent. Something like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
card_view:cardBackgroundColor="#DDFFFFFF"
card_view:cardElevation="#dimen/card_elevation">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
android:background="#drawable/card_background"/>
<LinearLayout
....
....
....
/LinearLayout>
</android.support.v7.widget.CardView>

Android NumberPicker deselect number

I have a slightly modified NumberPicker that I use and when the activity starts, the default value is already selected. This is annoying because it brings up the keyboard or brings up the dialog to cut/copy/paste. I did instruct the keyboard to stay down but it is still selected and will bring up the cut/copy/paste dialog. Once I scroll through the values the number is no longer selected and it acts normally. Does anyone know how to set the NumberPicker to not have anything selected at startup?
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class NumPicker extends NumberPicker
{
public NumPicker(Context context)
{
super(context);
}
public NumPicker(Context context, AttributeSet attrs)
{
super(context, attrs);
processAttributeSet(attrs);
}
public NumPicker(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
processAttributeSet(attrs);
}
/**
* Reads the xml, sets the properties
*/
private void processAttributeSet(AttributeSet attrs)
{
setMinValue(attrs.getAttributeIntValue(null, "min", 0));
setMaxValue(attrs.getAttributeIntValue(null, "max", 0));
setValue(4);
}
}
This is how it is used in the xml:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginRight="50dp"
android:layout_marginEnd="50dp"
android:layout_marginTop="40dp"
style="#style/CustomText"
max="100"
min="2"
The reason this happens is that the NumberPicker is the first (or only?) focusable element in your activity. You can trap the focus to your main layout view by adding this attribute to the root view:
android:focusableInTouchMode="true"

Custom preference not clickable

I added a custom preference to my project (code below). I added it to my preferences xml with a custom widgetLayout:
<w.PlusOnePreference
android:title="Rate App"
android:key="custom"
android:widgetLayout="#layout/plusone_pref"/>
Preference layout xml:
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.plus.PlusOneButton
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus"
android:id="#+id/plus_one_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:focusable="false"
plus:size="standard" />
I see the layout and the button in the layout works fine. The only problem is that the preference isn't clickable. Like it's hidden behind something.
Any ideas on how to make it clickable?
If I add a regular Preference (without a widget layout) it works fine.
Thanks.
public class PlusOnePreference extends Preference {
private PlusClient mPlusClient = null;
public PlusOnePreference(Context context) {
super(context);
}
public PlusOnePreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PlusOnePreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setPlusClient(PlusClient plusClient) {
mPlusClient = plusClient;
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
//mPlusOneButton =
PlusOneButton plusOneButton = (PlusOneButton)view.findViewById(R.id.plus_one_button);
plusOneButton.initialize(mPlusClient, SettingsActivity.URL, SettingsActivity.PLUS_ONE_REQUEST_CODE);
}
}
in layout/plusone_pref.xml set android:focusable="false" for your Button
Putting Pskink's answer together with Ran's comment:
If your custom preference's layout is a ViewGroup (e.g. a *Layout), use android:descendantFocusability="blocksDescendants"
If it's just one View, use android:focusable="false"
Preferences don't have a clickable attribute, though there is an onClick() method. Tryandroid:selectable.

Categories

Resources