I've developed a custom compound view which has a Button and a ProgressBar in it. I'm using databinding in my app. Compound view is not accepting onClick event, how to sort this issue?
<com.ui.custom.LoadingButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/bg_color"
android:onClick="#{()->viewModel.onNextClick()}"
android:text="#string/next"
android:textColor="#color/white"
app:isLoading="#{viewModel.isLoading}" />
Layout of Loading Button:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<FrameLayout
android:id="#+id/parentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:textSize="#dimen/btn_text_size" />
<com.wang.avi.AVLoadingIndicatorView
android:id="#+id/loading_indicator"
android:layout_width="#dimen/btn_loading_indicator"
android:layout_height="#dimen/btn_loading_indicator"
android:layout_gravity="center"
android:elevation="#dimen/cardview_default_elevation"
app:indicatorName="LineSpinFadeLoaderIndicator" />
</FrameLayout>
</layout>
Or If I use 'onClick' attribute of android, then how can i get it in TypedArray? So i can set it to view programmatically.
<declare-styleable name="LoadingButton">
<attr name="isLoading" format="boolean" />
<attr name="android:text" />
<attr name="android:textColor" />
<attr name="android:background" />
<attr name="android:onClick" />
</declare-styleable>
LoadingButton java
#BindingMethods({
#BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends LinearLayout implements View.OnClickListener {
private Context mContext;
private int background, textColor;
private boolean isLoading;
private String btnText;
private LayoutLoadingBtnBinding itemViewBinding;
private OnLoadingButtonListener listener;
public LoadingButton(Context context) {
super(context);
initializeView(context, null, 0);
}
public LoadingButton(Context context, AttributeSet attrs) {
super(context, attrs);
initializeView(context, attrs, 0);
}
public LoadingButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initializeView(context, attrs, defStyleAttr);
}
private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
mContext = context;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);
try {
background = array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
textColor = array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
btnText = array.getString(R.styleable.LoadingButton_android_text);
isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
// Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
} finally {
array.recycle();
}
itemViewBinding = LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
// setOnClickListener(this::onClick);
setValues();
}
private void setValues() {
try {
if (background != Integer.MAX_VALUE)
itemViewBinding.parentFrame.setBackgroundColor(background);
if (background != Integer.MAX_VALUE) {
itemViewBinding.button.setTextColor(textColor);
itemViewBinding.loadingIndicator.setIndicatorColor(textColor);
}
itemViewBinding.button.setText(btnText);
updateLoadingViews();
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateLoadingViews() {
itemViewBinding.button.setVisibility(isLoading ? INVISIBLE : VISIBLE);
itemViewBinding.loadingIndicator.setVisibility(isLoading ? VISIBLE : GONE);
}
public void setLoading(boolean isLoading) {
if (this.isLoading != isLoading) // update only if loading state is changed
{
this.isLoading = isLoading;
updateLoadingViews();
}
}
public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
AppLogger.d("usm_loading_btn_0", "setOnLoadingButtonClick is called: listener= " + (listener != null));
this.listener = listener;
}
#Override
public void onClick(View view) {
AppLogger.d("usm_loading_btn_1", "onClick is called");
if (listener != null) {
listener.onLoadingButtonClick();
}
}
public interface OnLoadingButtonListener {
void onLoadingButtonClick();
}
}
You can not using this way
<attr name="android:onClick" />
Try to using BindingMethods
#BindingMethods({
#BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends YOUR_ROOT_VIEW implements View.OnClickListener {
// your item view class.
private OnLoadingButtonListener listener;
public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
this.listener = listener;
}
#Override
public void onClick(View view) {
if (listener != null) {
listener.onLoadingButtonClick();
}
}
public interface OnLoadingButtonListener {
void onLoadingButtonClick();
}
}
and in your layout
<com.ui.custom.LoadingButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/bg_color"
android:onLoadingButtonClick="#{()->viewModel.onNextClick()}"
android:text="#string/next"
android:textColor="#color/white"
app:isLoading="#{viewModel.isLoading}" />
UPDATE 1
If your onClick() not working, remove it and try to using this way
private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
mContext = context;
TypedArray array =
context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);
try {
background =
array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
textColor =
array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
btnText = array.getString(R.styleable.LoadingButton_android_text);
isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
// Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
} finally {
array.recycle();
}
itemViewBinding =
LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);
itemViewBinding.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
listener.onLoadingButtonClick();
}
}
});
}
Related
I have implement a checkable CardView by following https://medium.com/#AlbinPoignot/checkable-cardview-in-all-android-versions-7124ca6df1ab
However, I need to let the user select just one option.
To clarify, if one is already checked, and the user select other, I need to deselect the previous option.
Furthermore, I need to when return the selected CardView keeps the checked state.
Could someone help me with this 2 tasks? Below is my implementation:
public class CheckableCardView extends CardView implements Checkable {
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
private boolean isChecked;
private TextView itemText;
public CheckableCardView(Context context) {
super(context);
init(null);
}
public CheckableCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CheckableCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
LayoutInflater.from(getContext()).inflate(R.layout.checkable_card_view, this, true);
setClickable(true);
setChecked(false);
setCardBackgroundColor(ContextCompat.getColorStateList(getContext(), R.color.selector_card_view_background));
if (attrs != null) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CheckableCardView, 0, 0);
try {
String text = ta.getString(R.styleable.CheckableCardView_card_text);
itemText = (TextView) findViewById(R.id.text);
if (text != null) {
setText(text);
}
} finally {
ta.recycle();
}
}
}
public void setText(String text){
itemText.setText(text);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
#Override
public boolean performClick() {
toggle();
return super.performClick();
}
#Override
public void setChecked(boolean checked) {
this.isChecked = checked;
}
#Override
public boolean isChecked() {
return isChecked;
}
#Override
public void toggle() {
setChecked(!this.isChecked);
}
}
You can also use the MaterialCard provided by the Material Components Library.
This card implement a Checkable interface by default.
Just use the android:checkable attribute in the xml:
<com.google.android.material.card.MaterialCardView
android:checkable="true"
..>
or setCheckable(true) in your code.
A way of switching to checked state is:
final MaterialCardView cardView = findViewById(R.id.card);
cardView.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) {
//cardView.setChecked(!cardView.isChecked());
cardView.toggle();
}
});
For those who are looking for an easy solution to this problem, here is the code:
cardONE.setOnClickListener {
cardONE.isChecked = true // set the current card to checked
cardTWO.isChecked = false // set the other card to unchecked
}
cardTWO.setOnClickListener {
cardTWO.isChecked = true
cardONE.isChecked = false
}
Or the function:
fun setChecked(checkCard: MaterialCardView, uncheckCard: MaterialCardView){
checkCard.isChecked = true
uncheckCard.isChecked = false
}
cardONE.setOnClickListener {
setChecked(it as MaterialCardView, cardTWO)
}
It's maybe not the most "elegant" way, but it works like a charm.
Needed Dependencies
implementation "com.google.android.material:material:1.2.0"
XML File
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardONE"
<!-- THIS IS NEEDED -->
android:checkable="true"
android:clickable="true"
android:focusable="true" />
You can do that by declare:
private List<CheckableCardView> checkableCardViewList = new ArrayList<>();
then you can add your cards to your list in "onBindViewHolder"
checkableCardViewList.add(position,holder.cardView);
finally you can add a callback function like "onClick"
holder.cardView.setOnClickListener(new CheckableCardView.OnClickListener() {
#Override
public void onClick(boolean b) {
if (b) {
for(CheckableCardView checkableCardView : checkableCardViewList) {
checkableCardView.setChecked(false);
}
checkableCardViewList.get(position).setChecked(true);
notifyDataSetChanged();
}
}
});
for call back you can add this to your CheckableCardView at bottom
public void setOnClickListener(OnClickListener onClickListener) { this.onClickListener = onClickListener;}
public interface OnClickListener {
void onClick(boolean b);
}
and at the top
private OnClickListener onClickListener;
#Override
public boolean performClick() {
toggle();
onClickListener.onClick(this.isChecked);
return super.performClick();
}
I've been using 2-way databinding for a basic application, it was going pretty well, until i start with custom views and attrs.
I want to create a custom view, with has a TextView and a EditText, and use it inside another layout:
<TextView
android:text="Holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvTitle"
android:layout_weight="1" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="none"
android:text="Name"
android:ems="10"
android:id="#+id/etAnwser"
android:layout_weight="1" />
And i have the custom attr for it
<resources>
<declare-styleable name="form_item">
<attr name="tvTitle" format="string" />
<attr name="anwserHint" format="string" />
<attr name="anwserText" format="string" />
<attr name="android:enabled" />
</declare-styleable>
In the fragment i do the following:
<rhcloud.com.financialcontrol.tabutil.FormItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="#{state.get()}"
form_item:anwserText='#={expense.description}'
form_item:tvTitle="Description:" />
It works nice has 1-way databind, but whatever i change the text, he don't send me the callback in class
#InverseBindingMethods(value = {
#InverseBindingMethod(type = FormItem.class, attribute = "anwserText"),
})
public class FormItem extends LinearLayout {
private TextView tvTitle;
private EditText etAnwser;
public FormItem(#NonNull Context context) {
super(context);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.form_item, this);
tvTitle = (TextView) findViewById(R.id.tvTitle);
etAnwser = (EditText) findViewById(R.id.etAnwser);
}
public FormItem(#NonNull Context context, #NonNull String title) {
this(context);
setTvTitle(title);
}
public FormItem(#NonNull Context context, #NonNull String title, #NonNull String hint) {
this(context, title);
setAnwserHint(hint);
}
public FormItem(#NonNull Context context, #NonNull String title, #NonNull String hint, #NonNull String anwserText) {
this(context, title, hint);
setAnwserHint(anwserText);
}
public FormItem(#NonNull Context context, #NonNull AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.form_item, this);
tvTitle = (TextView) findViewById(R.id.tvTitle);
etAnwser = (EditText) findViewById(R.id.etAnwser);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.form_item,
0, 0);
try {
setTvTitle(a.getString(R.styleable.form_item_tvTitle));
setAnwserHint(a.getString(R.styleable.form_item_anwserHint));
setAnwserText(a.getString(R.styleable.form_item_anwserText));
String isEnabled = a.getString(R.styleable.form_item_android_enabled);
if (isEnabled != null) {
setEnable(Boolean.parseBoolean(isEnabled));
}
} finally {
a.recycle();
}
}
public void setTvTitle(String title) {
tvTitle.setText(title);
}
public String getTvTitle() {
return tvTitle.getText().toString();
}
public void setAnwserHint(String hint) {
etAnwser.setHint(hint);
}
public String getAnwserHint() {
return etAnwser.getHint().toString();
}
public void setEnable(boolean isEnable) {
tvTitle.setEnabled(isEnable);
etAnwser.setEnabled(isEnable);
}
public void setAnwserText(String anwserText) {
etAnwser.setText(anwserText);
}
public String getAnwserText() {
return etAnwser.getText().toString();
}
#InverseBindingAdapter(attribute = "form_item:anwserText")
public static String setOnAnwserTextAttrChanged(final String value){
Log.d("Test","Calling InverseBindingAdapter: " + value);
return value;
}
#BindingAdapter(value = {"anwserTextAttrChanged"},
requireAll = false)
public static void setOnAnwserTextAttrChanged(final FormItem view,final InverseBindingListener anwserTextAttrChanged){
Log.d("Test","Calling BindingAdapter: " + view.getAnwserText());
if(anwserTextAttrChanged == null){
}else{
Log.d("Test","Calling here");
anwserTextAttrChanged.onChange();
}
}
#BindingAdapter(value = {"android:enabled"})
public static void customEnable(FormItem formItem, boolean isEnable) {
formItem.setEnable(isEnable);
}
}
Does anyone know how to make it work properly?
Fully code can be found at here
This works for me:
#InverseBindingMethods(value = {
#InverseBindingMethod(type = FilterPositionView.class, attribute = "bind:filterStringValue", method = "getFilterValue", event = "android:filterStringValuetAttrChanged")
})
public class FilterPositionView extends LinearLayout {
private FilterPositionBinding mBinding;
public FilterPositionView(Context context) {
super(context);
init(context);
}
public FilterPositionView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public FilterPositionView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public FilterPositionView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
mBinding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.filter_position, this, true);
setOrientation(HORIZONTAL);
mBinding.filterPositionCheck.setOnCheckedChangeListener((buttonView, isChecked) -> {
mBinding.filterPositionValue.setEnabled(isChecked);
if (!isChecked) mBinding.filterPositionValue.setText("");
});
}
/**
* Zwraca wpisywany text
*
* #return wpisane litery tekstu
*/
public String getFilterValue() {
return mBinding.filterPositionValue.getText().toString();
}
#BindingAdapter(value = {"bind:filterTitle", "bind:filterStringValue", "bind:filterDateValue"}, requireAll = false)
public static void setFilterBinding(FilterPositionView positionView, String filterTitle,
String filterStringValue, Long filterDateValue) {
positionView.mBinding.filterPositionTitle.setText(filterTitle);
if (filterStringValue != null)
positionView.mBinding.filterPositionValue.setText(filterStringValue);
if (filterDateValue != null)
positionView.mBinding.filterPositionValue.setText(DateTimeFormatUtil.format(filterDateValue));
}
#BindingAdapter(value = {"android:afterTextChanged", "android:filterStringValuetAttrChanged"}, requireAll = false)
public static void setTextWatcher(FilterPositionView filterPositionView, final TextViewBindingAdapter.AfterTextChanged after,
final InverseBindingListener textAttrChanged) {
TextWatcher newValue = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (after != null) {
after.afterTextChanged(s);
}
if (textAttrChanged != null) {
textAttrChanged.onChange();
}
}
};
TextWatcher oldValue = ListenerUtil.trackListener(filterPositionView.mBinding.filterPositionValue, newValue, R.id.textWatcher);
if (oldValue != null) {
filterPositionView.mBinding.filterPositionValue.removeTextChangedListener(oldValue);
}
filterPositionView.mBinding.filterPositionValue.addTextChangedListener(newValue);
}
}
Of course You have to add #={} in your XML layouts like below:
<com.example.customviews.FilterPositionView
style="#style/verticalLabeledValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:filterTitle="#{#string/filter_product}"
bind:filterStringValue="#={sfmodel.product}"/>
I am trying to create a custom view in android. With following condition :
The view should be initialize only once
The same view should be used throughout application
I have tried to initialize the view from application class and adding to the current activity.
Following is the code :
ViewInAppApplcation
public class ViewInAppApplcation extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new AppActivityCallBack());
}
private class AppActivityCallBack implements ActivityLifecycleCallbacks {
StatusBarView statusBarView = null;
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
final Activity activity1 = activity;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (statusBarView == null) {
statusBarView = new StatusBarView(activity1);
}
}
});
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
LinearLayout view = (LinearLayout) activity.findViewById(R.id.status_bar_view_holder);
if (view != null) {
view.addView(statusBarView, 0);
}
}
#Override
public void onActivityPaused(Activity activity) {
LinearLayout view = (LinearLayout) activity.findViewById(R.id.status_bar_view_holder);
if (view != null) {
view.removeView(statusBarView);
}
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
}
StatusBarView
public class StatusBarView extends RelativeLayout{
/**Activity context object.*/
private Context context = null;
/** View object */
private StatusBarView statusBarView = null;
/**
* Constructor
*
* #param context - Context Reference
*
*/
public StatusBarView(Context context) {
super(context);
this.context = context;
this.statusBarView = this;
initView();
}
/**
* Constructor
*
* #param context - Context Reference
* #param attrs - Set of attributes
*/
public StatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.statusBarView = this;
initView();
}
/**
* Constructor
*
* #param context - Context Reference
* #param attrs - Attribute List
* #param defStyleAttr - Default Style Attributes
*/
public StatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
this.statusBarView = this;
initView();
}
/**
* Inflate the app status bar xml and add to view
*/
private void initView() {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.view_app_status_bar, this, false);
new Asy().execute();
statusBarView.addView(view);
}
public void setValue(String value) {
TextView textView = (TextView) findViewById(R.id.txt_status);
textView.setText(value);
}
private class Asy extends AsyncTask<Void,Integer,String>
{
#Override
protected String doInBackground(Void... params) {
for (int i=0;i<20;i++)
{
publishProgress(i);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "DONE";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
setValue(values[0]+"");
}
}
}
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical">
<LinearLayout
android:background="#color/colorAccent"
android:id="#+id/status_bar_view_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<Button
android:id="#+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
This code will add a statusbar view to current activity. Is there any other way to do it?
I have a custom switch control class MySwitch
public class MySwitch extends RelativeLayout implements CompoundButton.OnCheckedChangeListener {
//private final Context context;
private String swKey;
private Integer swIcoOn, swIcoOff;
Switch mySW;
ImageView swIco;
SharedPreferences preferences;
public MySwitch(Context context) {
super(context, null);
}
public MySwitch(Context context, AttributeSet attrs) {
this(context, attrs, R.layout.my_switch);
}
public MySwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
preferences = PreferenceManager.getDefaultSharedPreferences(context);
LayoutInflater.from(context).inflate(defStyleAttr, this, true);
//View.inflate(context, defStyleAttr, this);
swIco = (ImageView) findViewById(R.id.swIcon);
TextView myText = (TextView) findViewById(R.id.swTitle);
TextView mySummary = (TextView) findViewById(R.id.swSummary);
mySW = (Switch) findViewById(R.id.mySW);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MySwitch, 0, 0);
try {
myText.setText(ta.getString(R.styleable.MySwitch_android_title));
mySummary.setText(ta.getString(R.styleable.MySwitch_android_summary));
mySW.setTextOn(ta.getString(R.styleable.MySwitch_android_switchTextOn));
mySW.setTextOff(ta.getString(R.styleable.MySwitch_android_switchTextOff));
mySW.setOnCheckedChangeListener(this);
swIcoOn = ta.getResourceId(R.styleable.MySwitch_icoOn, 0);
swIcoOff = ta.getResourceId(R.styleable.MySwitch_icoOff, 0);
swKey = ta.getString(R.styleable.MySwitch_android_key);
update();
} finally {
ta.recycle();
}
}
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
update(b);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(swKey, b);
editor.commit();
}
public void update(Boolean val) {
mySW.setChecked(val);
if(val)
swIco.setImageResource(swIcoOn);
else
swIco.setImageResource(swIcoOff);
}
public void update() {
update(preferences.getBoolean(swKey, false));
}
}
i want to reuse the code from this class in a SwitchPreference because the code is almost identical, so the class for it is
public class MySwitchPref extends SwitchPreference{
MySwitch obj;
private SharedPreferences preferences;
public MySwitchPref(Context context, AttributeSet attrs) {
super(context, attrs);
//setLayoutResource(R.layout.my_switch);
obj = new MySwitch(context,attrs);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
obj.update();
}
}
The issue is that on the SwitchPreference the Icon is not shown.
How can i get the icon to show also in the SwitchPreference?
I have a widget View as below:
public class RemoteNumView extends FrameLayout {
how call I use Roboguice just as in RoboActivity? As below:
#InjectView(R.id.btn_remote_control_num_0)
private TextView mText;
Full code is:
/**
* Created by bbcv on 13-12-12.
*/
public class RemoteNumView extends FrameLayout {
private IService mService;
#InjectView(R.id.btn_remote_control_num_0)
private TextView mText;
public RemoteNumView(Context context) {
super(context);
///
addView(LayoutInflater.from(context).inflate(R.layout.v_remote_control_fun,null));
}
public RemoteNumView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RemoteNumView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setService(IService service){
mService = service;
}
}
Anyone can HELP?
Solved it by writing custom code. Roboguice is badly written for this purpose.
protected void injectViews() {
for (Field field : this.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(InjectView.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new UnsupportedOperationException("Views can't be staticaly assigned.");
} else {
if (View.class.isAssignableFrom(field.getType())) {
try {
final InjectView injectView = field.getAnnotation(InjectView.class);
;
final int id = injectView.value();
View view = findViewById(id);
if ((view == null) && Nullable.notNullable(field)) {
throw new NullPointerException(String.format("Can't inject null value into %s.%s when field is not #Nullable", field.getDeclaringClass(), field.getName()));
}
field.setAccessible(true);
field.set(this, view);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
} else {
throw new UnsupportedOperationException("Need view type to assign");
}
}
}
}