setCompoundDrawables not displaying icon - android-studio

Currently,
I am implementing a Fragment to change the user password. To do so the user has to confirm his password. When both password's match I want to display an icon inside the EditText. to verify this while the user is typing I implemented the following function:
private fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(editable: Editable?) {
afterTextChanged.invoke(editable.toString())
}
})
}
Doing so I can use editText.afterTextChanged{...} to compare the values of the two editTexts. When both values match I am currently trying to display the icon with the following code:
val icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_baseline_check_circle_24,
null
)
icon?.setBounds(
0, 0,
icon.intrinsicWidth,
icon.intrinsicHeight
)
editText.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null)
Unfortuantly this is not working. I already tried using setCompoundDrawables instead of setCompoundDrawablesWithIntrinsicBounds but it makes no difference. Furthermore, I tried using R.drawable.ic_baseline_check_circle_24 directly in the function, but it is not working either.
Does somebody have an idea what's wrong with my implementation?

You need to overwrite the previous Drawable before setting the new Drawable.
The description of the Android document about the function is as follows:
Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables' bounds will be set to their intrinsic bounds.
Calling this method will overwrite any Drawables previously set using setCompoundDrawablesRelative(Drawable, Drawable, Drawable, Drawable) or related methods.
So you need to first set Drawable to null and then try again.
val icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_baseline_check_circle_24,
null
)
icon?.setBounds(
0, 0,
icon.intrinsicWidth,
icon.intrinsicHeight
)
editText.setCompoundDrawables(null, null, null, null) //add this line code
editText.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null)

Related

Android studio Kotlin OnClickListerner function

When I implemented the member in the class for the on click listener as shown below:
class QuizQuestionsActivity : AppCompatActivity(), View.OnClickListener {
I was given the option of implementing it as:
override fun onClick(p0: View?) {
I need it to be
override fun onClick(v: View?) {
can someone explain the difference and why I am not getting the option of v: View
Kotlin provide default parameter with alphabets and digits you can simply change it with your variable name like --
override fun onClick(v: View?) { }
override fun onClick(view: View?) { }
override fun onClick(myView: View?) { }
It's quit good and it's meaningful variable name that remember as long time. where P0 and P1 named variable is not like good to remember.
Hope You can understand what I mean to say.
Both of those functions are the same, it's just a different name for the View variable. Kotlin parameters are listed with the parameter name first, then the class name.
If you want p0 to be v instead, just change the parameter name to be v.

In FLUTTER / DART, why do we sometimes add a question mark to "String" when declaring a variable?

In the demo app, we find an instance of "final String? title;" - > Why do we add this "?" after the type String ?
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, this.title}) : super(key: key);
**final String? title;**
#override
_MyHomePageState createState() => _MyHomePageState();
}
In the same way, why when using it, we add a "!" ?
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: **Text(widget.title!),**
),
body: Center(
variable_type ? name_of_variable; means that name_of_variable can be null.
variable_type name_of_variable1; means that name_of_variable1 cannot be null and you should initialize it immediately.
late variable_type name_of_variable2; means that name_of_variable2 cannot be null and you can initialize it later.
late variable_type name_of_variable3;
variable_type ? name_of_variable4;
name_of_variable4=some_data;
name_of_variable3=name_of_variable4!;// name_of_variable4! means that you are sure 100% it never will be null
Real example with int type:
int ? a=null; // OK
int b=null; // b cannot be equal null
late int c =null; // c cannot be equal null
late int d;
d=5; //OK
late int d; // if you never initialize it, you'll get exception
int e=5;
int? f=4;
int ? z;
e=f!; // OK, You are sure that f never is null
e=z!;// You get exception because z is equal null
This is with null safety, the question mark means that this String? can possibly be null and flutter will allow you to assign null to it. String can never be null and you'll get an error before compiling.
If you define a variable String? name, and you want to use it later in a Text widget, you'll get an error. Because Text widgets only accept non-nullable types. But if you are sure that name will never be null, you tell flutter to not worry about it and that you know what you are doing, you do this by adding the ! like this : Text(name!).
I believe adding a ? is a null safety feature introduced in the recent time flutter update. It basically means the value can be null and it won't throw any error

MVVMCross updating binding to UITableViewCell

I'm wondering if I'm doing this the correct way - this method works, but feels somewhat 'dirty'. Essentially, a button in an MvxTableViewCell changes a parameter of the bound object, but the cell does not update to reflect the change until it's scrolled out of view and back into view (ie the cell is 'redrawn'). All the examples here are simplified, but you get the idea..
Firstly, my object:
public class Expense
{
public decimal Amount { get; set; }
public bool Selected { get; set; }
public Command FlipSelected
{
get { return new MvxCommand(()=> this.Selected = !this.Selected); }
}
}
Secondly, my cell (in the constructor) contains:
this.DelayBind(() =>
{
var set = this.CreateBindingSet<HistoryCell, Expense>();
set.Bind(this.TitleText).To(x => x.Amount);
set.Bind(this.SelectButton).To(x=> x.FlipSelected);
set.Bind(this.SelectButton).For(x => x.BackgroundColor).To(x => x.Selected).WithConversion(new ButtonConverter(), null);
set.Apply();
});
And i have a valueconverter that returns the background colour of the button:
class ButtonConverter : MvxValueConverter<bool, UIColor>
{
UIColor selectedColour = UIColor.FromRGB(128, 128, 128);
UIColor unSelectedColour = UIColor.GroupTableViewBackgroundColor;
protected override UIColor Convert(bool value, Type targetType, object parameter, CultureInfo culture)
{
return value ? selectedColour : unSelectedColour;
}
protected override bool ConvertBack(UIColor value, Type targetType, object parameter, CultureInfo culture)
{
return value == selectedColour;
}
}
Right, so what happens is, if i click the button in the cell, it runs the command that flips the bool value Selected, which in turn binds back to the background colour of the cell via the ButtonConverter value converter.
The problem I'm having is that the cell doesn't update straight away - only when I scroll out of view of that cell and back into view (ie the cell is redrawn). So i thought I'd just cause the cell to become 'dirty':
this.SelectButton.TouchUpInside += (o, e) =>
{
this.SetNeedsDisplay();
};
But this doesn't work. What does work is putting additional code inside the TouchUpInside event that manually changes the background colour. But I'm assuming this isn't the correct way of doing it.
Do I need to trigger RaisePropertyChanged when I change the value of Selected in the Expense object? How can I do that when it's just an object?
Really hoping Stuart can help out on this one ;)
I think your analysis is correct - the UI isn't updating live because there are no change messages from your Expense objects.
To provide 'traditional' change notifications in your view model objects, you need to make sure each one supports INotifyPropertyChanged. This small interface is easy to implement yourself if you want to - or you can modify your Expense to inherit the built-in MvxNotifyPropertyChanged helper class if you prefer - then RaisePropertyChanged would be available.
As one other alternative, you can also implement the new 'Rio' field based binding if you prefer. For an intro to this, see N=36 in http://mvvmcross.blogspot.com

Generic used in conjunction with Sort(Comparison<T>)

Im wondering if its possible to reuse my overload of the Sort(Comparison) method to sort both labels and textboxes by tabIndex. Ive already tried and i couldnt get it to work. Any help would be appreciated.
foreach(Control control in gbUserInputs.Controls)
{
if (control is Label)
{
inputLabels.Add((Label)control);
}
if (control is TextBox)
{
inputTxtboxes.Add((TextBox)control);
}
}
Sort method call(this doesnt work).
inputLabels.Sort(sortMyInputs<Label>);
Overload of sort method.
private static int sortMyInputs<T>(T entry1, T entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You shouldn't be making a generic method:
private static int CompareLabels(Label entry1, Label entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
The point of a generic delegate is to allow it to hold methods of different concrete types; not to allow it to hold methods that are themselves generic.
If you want to reuse your method, you can modify it to take Control (which both TextBox and Label inherit); you would still be able to pass it to List<Label>.Sort because of delegate covariance.
If you're using .Net < 4, which doesn't have delegate covariance, you can do it your way by adding a constraint to the method so that it knows what T can be:
private static int CompareLabels<T>(T entry1, T entry2) where T : Control
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You can also simply replace all of your code with one line of LINQ:
inputLabels = gbUserInputs.Controls.OfType<Label>()
.OrderBy(c => c.TabIndex)
.ToList();

Customise ReSharper generated Properties code

With reSharper -> Edit -> Generate Code -> Properties from this:
private int _age;
I get this
public int Age
{
get { return _age; }
set { _age = value; }
}
which is alright, but what can I do if I want something like this:
public int Age
{
get { return _age; }
set
{
if (_age != value)
{
_age = value;
OnPropertyChanged("Age");
}
}
}
Is there a way to customise ReSharper's output? FYI I'm on Visual Studio 2008, ReSharper v5.1.
You could write your own ReSharper Live Template like so:
Then you can enter new properties with backing field and OnPropertyChangedEvent call by one step by typing in first letters of live template shortcut: propWithChangeEvents.
Then an intellisence list appears. You select propWithChangeEvents, type the field type (i.e. int) and ENTER, then field name (i.e. age) and ENTER.
Then all is generated as you need.
That's for new fields/properties. If you really need the same for existing fields let me know it.
You could create a live template to do what you want. I have a couple templates I use for custom property implementations. It's pretty powerful stuff.

Resources