I have a extended EditText and I can not call any standard function with the following situation:
MainActivity
private Editor sEditor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ex);
sEditor = (Editor)findViewById(R.id.s_editor);
}
private String retText() {
return sEditor.getText.toString();
}
Editor
public Editor(Context context) {
super(context);
init();
}
public Editor(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Editor(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
}
When retText() is called:
Attempt to invoke virtual method 'android.text.Editable com.paulo.ex.Editor.getText()' on a null object reference
I also tried to initialize Editor as sEditor = new Editor(MainActivity.this); but the return value of retText() is always null. What is the appropriate way to resolve this problem?
Related
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 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");
}
}
}
}
I am new in android and I want use my custom font for my app. I wrote 2 ways creating custom font. Could you tell me guys which one is better and faster.
first way is using singleton class second way is create my own textview.
with singleton
public class FontFactory {
private static FontFactory instance;
private HashMap<String, Typeface> fontMap = new HashMap<String, Typeface>();
private FontFactory() {
}
public static FontFactory getInstance() {
if (instance == null){
instance = new FontFactory();
}
return instance;
}
public Typeface getFont(DefaultActivity pActivity,String font) {
Typeface typeface = fontMap.get(font);
if (typeface == null) {
typeface = Typeface.createFromAsset(pActivity.getResources().getAssets(), "fonts/" + font);
fontMap.put(font, typeface);
}
return typeface;
}
}
with own textview
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setFonts(context,attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFonts(context,attrs);
}
private void setFonts(Context context, AttributeSet attrs){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView_customFont);
String ttfName = a.getString(R.styleable.MyTextView_customFont_ttf_name);
setCustomTypeFace(context, ttfName);
}
public void setCustomTypeFace(Context context, String ttfName) {
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/MuseoSansCyrl_"+ttfName+".otf");
setTypeface(font);
}
#Override
public void setTypeface(Typeface tf) {
super.setTypeface(tf);
}
}
In your custom textview approach, you are creating the Typeface object every time you create a CustomTextView (or change its typeface), while your factory would keep the already loaded ones around in memory and re-use them.
The approach with a custom text view may work fine in some instances, but if you suddenly need to create a lot of them (or change the typeface on a lot of them), it might noticably slow down your performance as in this question with a scrollview.
I'd choose the singleton.
I'm currently programming in Monodroid and I'm having an issue with the extension of a Listview.
I currently have ListView extended like this:
public class TTListView : ListView
{
private Context mContext;
private bool wrapAdapter;
public TTListView(Context context) :
base(context)
{
Initialize();
this.mContext = context;
}
public TTListView(Context context, IAttributeSet attrs) :
base(context, attrs)
{
Initialize();
this.mContext = context;
}
public TTListView(Context context, IAttributeSet attrs, int defStyle) :
base(context, attrs, defStyle)
{
Initialize();
this.mContext = context;
}
private void Initialize()
{
this.CacheColorHint = Color.Transparent;
//Still some more stuff to be added here
}
public void InsertItemAt(int index)
{
Animation anim = AnimationUtils.LoadAnimation(
mContext, Resource.Animator.slide_top_down);
anim.Duration = 500;
this.GetChildAt(index).StartAnimation(anim);
}
public void SetDelegate(TTListDelegate _delegate)
{
this.OnItemClickListener = (IOnItemClickListener)_delegate;
this.OnItemLongClickListener = (IOnItemLongClickListener)_delegate;
}
public override void AddFooterView(View v)
{
base.AddFooterView(v);
wrapAdapter = true;
}
/*public override IListAdapter Adapter
{
get
{
return base.Adapter;
}
set
{
//Check if the passed parameter is a TTListAdapter
TTListAdapter _ttadapter = value as TTListAdapter;
if (_ttadapter != null)
{
_ttadapter.Wrapped = wrapAdapter;
}
base.Adapter = value;
}
}*/
}
The above code works perfectly fine.
The problem with this is when I'm trying to override the Adapter property (which is now commented out) I get the following exception when trying to create a TTListView object:
"Unable to activate instance of type TimeTellApp.TTListView from native handle 40557188. No constructor found for TTListView::.ctor(System.IntPtr, Android.Runtime.JniHandleOwner)"
Usually this has something to do with the GC destroying the managed mapped object so up until now I solved these kind of problems by keeping a reference to the object. The problem with the TTListView is that the exception already comes up when calling the constructor for initialization.
I create a TTListView object like this:
TTListView setting_listview = new TTListView(this);
(Where this is a Activity)
What could be the problem here and what would be the best way to solve it?
The error message says that you're missing a specific constructor in your class, which you should implement:
protected ListView (IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer)