Call View.OnClickListener from Snackbar - android

I am trying to call ViewModel from my activity in a snackbar and since it requires a onClickListener it doesn't let me just do a simple
Snackbar.make(mViewBinding.root, "Note has been deleted", Snackbar.LENGTH_LONG).apply {
setAction("Undo", mViewModel.insertNote(event.data!!))
}
So the solution is to call with a View.OnClickListener but I found a weird solution that I'm trying to understand and I'd like to know if any of you could explain to me this.
Snackbar.make(mViewBinding.root, "Note has been deleted", Snackbar.LENGTH_LONG).apply {
setAction("Undo"){
mViewModel.insertNote(event.data!!)
}
}
Question: Why does setting a "{" works the same way? Is it an anonymous function?

Related

this vs this#activity_main in context paramter for a function in kotlin

when i create a toast in android studio I got an error when writing the code like this
but I searched online w and I found that when I replace "this" with "this#main_activity" which is the current activity my code works and compiles.
So what is the difference between "this" and "this#main_activity" ?
class MainActivity :AppCompat(){
val playbackListener = object : YouTubePlayer.PlaybackEventListener{
Toast.makeText(this, "Good, video is playing ok", Toast.LENGTH_SHORT).show()
}
}
Your Toast.makeText() call is inside of an object:
object : YouTubePlayer.PlaybackEventListener {
Toast.makeText(this, "Good, video is playing ok", Toast.LENGTH_SHORT).show()
}
Therefore, the value of this is the object (the PlaybackEventListener).
In order to refer to the instance of the Activity that your object lives inside, you can qualify the this keyword: this#MainActivity

Simpler OnClickListener?

i am new and learning , i have checked many related posts but still my few following questions are unanswered...[Edited ]the language is java...
following is the way to handle the click on button but can any one explain
1, why i have to declare the anonymous class ,
2, how i know that i have to declare the anonymous class here or any where else could ?
3, why i cannot use simple the btn.setOnClickListener(); why i must have to call anonymous class here ... below line is simple to do the task ...!!
btn.setOnClickListener();
why to make two more lines of code ...? i.e
#override public void onClick (View v) {....}
======================
Button btnCount = (Button) findViewById(R.id.btnCountId);
btnCount.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) { ...... }
});
You are using a Java entity called an "interface".
View.setOnClickListener accepts an object of type "OnClickListener". So you first need to create an object of such a type.
The Object OnClickListener is indeed an interface with one function "onClick", so to create an object of that type you need to implement it (define all the functions in the interface) - in this case, only one.
OnClickListener myClickListener=new OnClickListener() {
#Override // override means you are implementing a function in the interface or a derived class
public void OnClick(View v) {
// the button has been pressed
}
};
and then you can assign it to a view:
myButton.setOnClickListener(myClickListener);
or to many views:
myButton1.setOnClickListener(myClickListener);
myButton2.setOnClickListener(myClickListener);
myButton3.setOnClickListener(myClickListener);
In Java you'll find objects use listener interfaces to communicate events.
Mind that more complex objects use interfaces that can have several methods instead of just one, that's when the simplification you see is not that handy.
Imagine an object "Girl" that has a method "flirt" that you can invoke to ask her for dinner. The Girl will take some time to decide, then communicate one of a lot possible answers with the same interface.
OnGirlFlirtListener myGirlFlirtListener=new OnGirlFlirtListener() {
#Override
public void onGirlSaidYes() {
// invite the girl to have dinner
}
#Override
public void onGirlSaidNo() {
// find another girl or hang with your mates instead
}
#Override
public void onGirlSaidMaybe() {
// ask her later
}
#Override
public void onParentsHateMe() {
// forget about that girl
}
}
Then you can do:
mGirl.flirt (myGirlFlirtListener);
And the code is indeed elegant: With one interface you control all the possible answers! It's the same for a lot of objects in java (and Android).
Instead of creating the listener as an object, and setting it, you can as well create it as an anonymous class if you won't reuse it, of course.
EDIT
How to create a generic clicklistener?
Sometimes, in the same dialog, you have 15 or 20 buttons that do more or less the same, and only differ in a detail. Although you can perfectly crete 20 clicklisteners, there's a cooler way taking advantage of View.setTag() function.
setTag allows you to store whatever object you want to any view. You use that do distinguish, inside a clicklistener, which button was pressed.
So imagine you have 5 buttons: Brian, Peter, Loise, Krasty and Sue:
mButtonPeter.setTag("Peter Griffin");
mButtonLouise.setTag("Louise Griffin");
mButtonBrian.setTag("Brian");
mButtonKrasty.setTag("Krasty");
mButtonSue.setTag("Sue");
OnClickListener personClickListener=new OnClickListener() {
#Override
public void OnClick(View buttonPressed) {
String person=(String)(buttonPressed.getTag());
// you pressed button "person"
Toast.makeText(buttonPressed.getContext(), "Hey, "+person+", how is it going!!", Toast.LENGTH_SHORT).show();
}
};
mButtonPeter.setOnClickListener(personClickListener);
mButtonLouise.setOnClickListener(personClickListener);
mButtonBrian.setOnClickListener(personClickListener);
mButtonKrasty.setOnClickListener(personClickListener);
mButtonSue.setOnClickListener(personClickListener);
Isn't it cool?
When you are "setting an onClickListener" what you are doing is telling: "when this button is clicked, execute this code".
The code to be executed is implemented in the provided annonymous function.
You can't simply do btn.setOnClickListener() without an argument because that would not provide the information regarding which behaviour to perform when the button is clicked.

onBackPressed() with arguments

I'm using onBackPressed() method in my app in few places.
In every place I want this method to do other stuff.
When user is in X layout I want to Back button does somethink else than in Y layout, so I'm thinking that the best solution would be to use arguments in onBackPressed method.
For example in X onBackPressed(0); and in Y onBackPressed(1); etc.
#Override
public void onBackPressed(int c){
if(c==0)Toast.makeText(getApplicationContext(), "This is X", Toast.LENGTH_SHORT).show();
if (c==1)Toast.makeText(getApplicationContext(), "This is Y", Toast.LENGTH_SHORT).show();
}
But it does not work.
Do You have any ideas what can I do to make it work ? Or is there any better solution for this problem?
you are overriding a framework method and you can't pass it any other parameters than those defined by the API. However you can create an own method to check what you need like:
#Override
public void onBackPressed(){
switch(checkLayout()){
case 1: //do stuff
break;
case 2: .....
}
}
And to extend CommonsWare's comment a little: yes, users are not "in a certain layout". Users are interacting with a certain Activity that is hosting a certain layout. If you don't really understand what this means, you should probably consult this document: http://developer.android.com/reference/android/app/Activity.html
The way overriding methods in Android works is that you must exactly duplicate the method header. When you change it, it will still compile, but Java will read it as an overloaded method and thus not do anything with it because it is never called.
You would be a lot better off handling an instance variable outside of onBackPressed() and then handling it when it's actually pressed.
The following is a simple implementation.
//Your instance variable
boolean myRandomInstanceVariable = true;
#Override
public void onBackPressed()
{
if(myRandomInstanceVariable)
{
//do stuff
}
else
{
//do other stuff
}
}
Create a field in your class set it to some value in some place to some other value in some other place. Then in onBackPressed() check that field's value and proceed accordingly.

Please explain this structure and why it's used like this?

I found the code segment below in [this tutorial][1]. I don't understand what exactly happens. It seems like the button is created and that a listener is then set to listen for when it's clicked, but why is the entire onClick(View view) method inside the (...) of the sendMail.setOnClickListener()?
Regarding setOnClickListener, Eclipse said:
Register a callback to be invoked when this view is clicked. If this view is not clickable, it becomes clickable.
So am I correct in saying that the structure is as it is to almost simultaneously see if the button is clickable, make it clickable if it isn't and create a listener for the button?
But I still don't understand why it was written and structured like this:
Button sendMail = (Button) findViewById(R.id.send_email);
sendMail.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Mail m = new Mail("email#gmail.com", "password");
m.setTo("email#gmail.com");
m.setFrom("email#gmail.com");
m.setSubject("This is an email sent using my Mail JavaMail wrapper from an Android device.");
m.setBody("Email body.");
try {
m.addAttachment("/sdcard/filelocation");
if(m.send()) {
Toast.makeText(m, "Email was sent successfully.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Email was not sent.", Toast.LENGTH_LONG).show();
}
} catch(Exception e) {
Toast.makeText(getApplicationContext(), "There was a problem sending the email.", Toast.LENGTH_LONG).show();
Log.e("MailApp", "Could not send email", e);
}
}
});
In my mind it should be:
sendMail.setOnClickListener();
sendMail.onClick(this);
public void onClick(View view) {...}
Any comments or Register a callback to be invoked when this view is clicked. If this view is not clickable, it becomes clickable.
This is basically a subclass. This method is known as anonymous subclassing. It allows to you to create a subclass and use it together.
Anonymous subclass do not have constructors as the class has no name. For that you need to use instance initialisers. Basically these classes are used when creating another class file for it feels redundant and if you want to keep the class code together in the same block(Atleast that why i use it for).
It is called an anonymous class. Instead of creating a new class with the class keyword, you just use the syntax new <superclass-or-interface-name>() { ... } with all the required methods.
Read more about anonymous classes at Wikibooks
It's called an anonymous inner class, its a common Java pattern. You are free to define an explicit class that implements the method and set your listener to it, instead.
That's just how it works when you create a new instance of the Listener inside the setOnClickListener() method. Nothing weird about that at all.
Alternatively, you can set a method for android:onClick in the button XML side. In code, you'll need to do the following:
public void testMethod(View v) {
// code
}

findViewById returns null when moved into a library file

I'm new to Java and Android. I have a piece of code that is used for multiple activities so I moved it into its own library .java file. However, now my findViewById return null where they used to return the right stuff when they were part of the main Activity file with onCreate() and setContentView() calls. How do I make it work inside my library?
Call from the Activity class:
helper.popupControl(getListView(), getBaseContext(), "on");
The code in the libruary:
public class Helper extends ListActivity {
public void popupControl (View v, Context context, String on_off) {
Animation aFilm = AnimationUtils.loadAnimation(context, R.anim.fade_in);
aFilm.reset();
View vFilm = (View) v.findViewById(R.id.gray_out_film);
if(vFilm==null) {
Toast maxToast = Toast.makeText(context, "View is null! "+R.id.gray_out_film+", View:"+v.toString(), Toast.LENGTH_LONG);
maxToast.setGravity(Gravity.CENTER, 0, 0);
maxToast.show();
} else {
Toast maxToast = Toast.makeText(context, "View is not null!", Toast.LENGTH_SHORT);
maxToast.setGravity(Gravity.CENTER, 0, 0);
maxToast.show();
}
}
}
This happened to me and the solution was to delete the main.xml from the new project. Somehow it was interfering with the main.xml from the library project even though I was referring to the fully qualified name (ex: library.package.R.layout.main).
Call Activity.setContentView(int resID) before calling findViewbyId()
What you're trying to do seems 'icky' but here's how it would be done.
You'll need to pass the View from the Activity...findViewbyId() is its Member function.
If you provide some sample code, i could be more helpfull.
Edit: Confused Context with View. Oops!

Categories

Resources