I am new to Android Development and I found that while using the setOnClickListener() Method the onClick function takes a parameter instead of an argument. why is onClick function's syntax is like user defined function? I am very much confused. Below is an image that reflects my point of view.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView display = findViewById(R.id.Display);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
display.setText("Ravikiran");
}
});
}
}
Here in the above code i am confused with the part of the code which is mentioned below.
public void onClick(View v) {
display.setText("Ravikiran");
}
Related
I am trying to make a button in activity2(settings page), when the button is clicked, then the title of activity1(MainActivity) will change to what I set to. I have been trying to use interface to carry out the function but it gives me a null pointer exception error.
MainActivity
#Override
public void changeActionBarTitle(String editText){
actionTitle = editText;
setTitle(actionTitle);
};
Interface
public interface ActionBarInterface {
void changeActionBarTitle(String editText);
}
Setting page (activity 2)
public class SettingsPage extends AppCompatActivity {
ActionBarInterface actionBarInterface;
Button editCompanyNameButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings_page);
setTitle("Settings");
editCompanyNameButton = findViewById(R.id.editCompanyNameButton);
editCompanyNameButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
actionBarInterface.changeActionBarTitle("test");
}
});
}
}
Thanks.
You can try this code without using the interface
MainActivity:
#Override
protected void onResume() {
setTitle(Main2Activity.title);
super.onResume();
}
activity2:
public class SettingsPage extends AppCompatActivity {
Button editCompanyNameButton;
static String title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
setTitle("Settings");
editCompanyNameButton = findViewById(R.id.editCompanyNameButton);
editCompanyNameButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
title = "test";
}
});
}
}
It gives a null pointer exception error because actionBarInterface was not initialised.
Check out topics on 'Getting a Result from an Activity', making use of classes and functions such as Intent, startActivityForResult, onActivityResult.
Android: how to make an activity return results to the activity which calls it?
Here is my code. I'm very new to Java and I know that this question is already been posted but still I didn't get the expected outpost so I had to post.
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MediaPlayer policeSound = MediaPlayer.create(this, R.raw.police);
Button policeSounds = (Button) this.findViewById(R.id.police);
policeSounds.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (policeSound.isPlaying()){
policeSound.stop();
}
else {
policeSound.start();
}
}
});
}
}
I tried adding onBackPressed() code to this but it couldn't detect the 'policeSound' as it was detected in the previous method!
And someone please even teach me how to use #Override annotations!
To detect the 'policeSound' in other methods you need to make it be a field of a class:
private MediaPlayer policeSound;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
policeSound = MediaPlayer.create(this, R.raw.police);
Button policeSounds = (Button) this.findViewById(R.id.police);
policeSounds.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (policeSound.isPlaying()) {
policeSound.stop();
} else {
policeSound.start();
}
}
}
);
}
In your codes policeSound is a local variable which is be seen only in Oncreate() method,as Oleh Sokolov said, you should declare policeSound as a field of class.
About #Override , you could see this good explanation
and in android studio , when you press ctrl + o in java class file, you can override superclass method, and IDE will add #Override automatically for you.
Below is an example of My app's MainActivity.java:
/*imports and other stuffs*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button myButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myButton = (Button) findViewById(R.id.first_button);
// myButton.setOnClickListener(this); by using it, app works as desired.
myButton.setOnClickListener(new MainActivity()); //What's wrong with this piece of codes?
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.first_button){
Toast.makeText(this, "Made it", Toast.LENGTH_SHORT).show();
}
}
As setOnClickListener() method requires an object of a class that implements View.setOnClickListener, it can be handled with a custom class implements View.setOnClickListener, but my question, as a beginner, is what's going on actually, while passing an object of MainActivity?
Edit:
But if I pass an object of another class and pass that one, the code works perfectly, doesn't it? and what about those codes:
public class MainActivity extends AppCompatActivity {
Button myButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myButton = (Button) findViewById(R.id.first_button);
myButton.setOnClickListener(new MyClass());
}
class MyClass implements View.OnClickListener{
#Override
public void onClick(View v) {
Log.d("buttontest","Working Perfectly");
}
}
}
myButton.setOnClickListener(new MainActivity());
With that piece of code you are setting on OnClickListener for your myButton. However, you are not creating the correct listener object. You are creating a new MainActivity object that is not the correct type.
myButton.setOnClickListener(this);
This is correct, because the class implements View.OnClickListener and has the implementation with the void onClick(View v) method in the class.
You can also do this if you like too:
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// add code here
}
});
This will create an new OnClickListener object with the onClick method implemented as well. This is passing an anonymous class to the setOnClickListener.
I am a beginner at Java and as not as familiar with its syntax as compared to C.
Specifically I have the follow code; there are 2 TextViews view1, view2, and I make the same Toast message pop up on clicking either TextViews
public class MainActivity extends ActionBarActivity {
private TextView view1, view2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view1 = (TextView)findViewById(R.id.item_1a);
view1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
});
view2 = (TextView)findViewById(R.id.item_1b);
view2.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
});
}
}
I realised that if there are 100 TextViews, it will be inefficient if i keep overriding onClick 100 times.
As such, is there a way to override onClick just once, and let all instances of setOnClickListener to refer back to the same onClick?
Thanks!
Define a class which implements OnClickListener along the lines of
class MyClickListener implements OnClickListener{
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
}
and then you can use the same class everywhere. For example:
// say you have 100 TextViews
for (int i = 0; i < views.length; i++)
views[i].setOnClickListener(new MyClickListener());
If it is the same message you can do it this way:
public class MainActivity extends ActionBarActivity {
private TextView view1, view2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "button clicked", Toast.LENGTH_SHORT).show();
}
};
view1 = (TextView) findViewById(R.id.item_1a);
view1.setOnClickListener(listener);
view2 = (TextView) findViewById(R.id.item_1b);
view2.setOnClickListener(listener);
}
}
Sure. What you are implementing are called "anonymous inner types".
OnClickListener listener = new OnClickListener()
{
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
};
view1 = (TextView)findViewById(R.id.item_1a);
view1.setOnClickListener(listener);
view2 = (TextView)findViewById(R.id.item_2a);
view2.setOnClickListener(listener);
Or you can create a subclass of the OnClickListener class, like #webuster answered.
You can probably affect your listener to a variable and assign it to views :
OnClickListener listener = new OnClickListener(){
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
};
view1.setOnClickListener(listener);
view2.setOnClickListener(listener);
You have to set the onclicklistener on each View but there is a cleaner way of doing so.
Put this in the Activity code:
public void myOnclickListener(View v) {
Toast.makeText(v.getContext(),"button clicked",Toast.LENGTH_SHORT).show();
}
Then set the click listener in your xml:
<TextView
android:id="#+id/mytext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="myOnclickListener"
/>
Well, Suppose there is an Activity called MainActivity and there are two layouts called layout1 and layout2 both have few buttons. By default MainActivity layout is layout1 like following:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout1);
Now what I did actually is by clicking a button in layout1 the second layout is set like following:
someBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout2);
}
});
There are another button in layout2 to return back to layout1 like following:
someBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout1);
}
});
Problem is when I returned back to layout1 then OnClickListener of someBtn1 is not working. It seems I need to set OnClickListener again for someBtn1 of layout1.
How I can write code to make them work perfectly with best practices ?
The best practice is to use fragments instead of change the content view.
In your code, setContentView with layouts recreate (inflate) all your views every time, so the call setContentView(R.layout.layout1) in someBtn2 click listener will create a new button without the associated listener.
If you don't want to use fragments you can do this:
private View view1, view2;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view1 = getLayoutInflater().inflate(R.layout.layout1, null);
view2 = getLayoutInflater().inflate(R.layout.layout2, null);
setContentView(view1);
The listeners will be:
someBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(view2);
}
});
someBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(view1);
}
});
If you just want to play around with your current code, a solution for your problem is that the listeners must be redeclared when the layout changes, as follows:
someBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout2);
someBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout1);
}
});
}
});
someBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout1);
someBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout2);
}
});
}
});
An alternative to avoid declaring the listeners twice is to declare two methods to handle the layout changes and use the onClick property of the button in each of the layouts, for example:
public void setLayout1(View view) {
setContentView(R.layout.layout1);
}
public void setLayout2(View view) {
setContentView(R.layout.layout2);
}
In layout1.xml:
<Button
android:id="#+id/someBtn1"
android:onClick="setLayout2"/>
In layout2.xml:
<Button
android:id="#+id/someBtn2"
android:onClick="setLayout1"/>
However, if you want to follow best practices, the best practice is not to mix layouts in the same activity, but instead declare two different activities (each one with its own layout) and call one activity or the other depending on the button that was clicked. Suppose that you are in Activity1 and want to call Activity2, then go back to Activity1:
In Activity1.java:
someBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(this, Activity2.class));
}
});
In Activity2.java:
someBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
One way of doing this is loading both views in onCreate(...), and then switching between them by making the one you don't want invisible. Something like the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutParams default_layout_params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
View view1 = inflater.inflate(R.layout.layout1, null);
addContentView(view1, default_layout_params);
View view2 = inflater.inflate(R.layout.layout2, null);
addContentView(view2, default_layout_params);
view2.setVisibility(View.INVISIBLE);
view1.setVisibility(View.VISIBLE);
view1.bringToFront();
At the time you callback layout1, data must be set again.
You could merge both layouts in one and then use ViewFlipper to switch between them.
When you are seting layout2, you should also set up OnClickListener to someBtn1 and vice versa, I'd suggest something like this. But as in prevoius answer, in general you should avoid mixing layouts in such manner.
public class MainActivity extends Activity {
private final View.OnClickListener setLayout1Listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout2);
((Button)findViewById(R.id.Btn2Id)).setOnClickListener(setLayout2Listener);
//do other stuff
}
};
private final View.OnClickListener setLayout2Listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
setContentView(R.layout.layout1);
((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
//do other stuff
}
};
#Override
public void onCreate(final Bundle savedInstance) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout1);
((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
//do other stuff
}
}