I have a main application with a button defined in layout.xml.
When I click on the button, I want to call a method located in another class, and when I try to create a TextView in that class, I must provide an argument to the new TextView(???) command, and I don't know what to do.
I reckon that this is a 2 seconds question for you folks, and for me, newbiiie as it is, it is a tough one.
Just in case, here are the relevant sections of code:
The section of the main class that is applicable:
public class MainActivity extends Activity {
public DateAndTime cur_datetime = new DateAndTime();
public LongLat cur_longlat = new LongLat();
public int current_location_number = 0;
public ArrayList<LocationInfo> locations = null;
Button doSunButton;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addListenersForButtons();
dosomething();
}
public void addListenersForButtons()
{
doSunButton = (Button) findViewById(R.id.dosun_button_id);
doSunButton.setOnClickListener( new OnClickListener()
{
#Override
public void onClick(View arg0)
{
DoSun myDoSun = new DoSun();
Log.v("button", "Am I really calling from the button function...");
myDoSun.doSun2(locations, current_location_number);
} // end of dosun on click on dosun_id button
); // end of define listener
} // end of addListenersForButtons(0) method
}
The class whose method is called:
package com.example.sunandmoon;
import java.util.ArrayList;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class DoSun extends Activity{
public void doSun2(ArrayList<LocationInfo> locations, int current_location_number)
{
//Log.v("doSun", "Am I really there!");
TextView textViewsunrise = new TextView(??????);
textViewsunrise = (TextView) findViewById(R.id.sunrise_id);
((TextView)textViewsunrise).setText("From DoSun2! " + locations.get(current_location_number).getnameGiven());
} // end of doSun(0) method
}
And by the way, I also wonder how I could avoid passing the two parameters current_location_numberv and ArrayList locations to the doSun2 method, since they "should be" globals (you can see that I come from C...).
Thank you for your help.
And to you flamers of all kinds, yes, I have tried to find an answer to this...
There are multiple problems in your code.
Do not use classes extended from Activity for anything other than, er, being Activities! An Activity represents a single task focused object with which the user interacts. Loosely, think of each screen in an app as being an Activity.
"should be globals". No they should not. There are occasional situations in Android in which globals make sense. This is not one of them. You should not avoid passing the arguments to doSun2() since it behaves according to those arguments. It would be completely anti-pattern to use globals.
The TextView you want to create rightly belongs to MainActivity. It should be responsible for creating and managing it. To do this, have the method in DoSun take arguments (locations, currentLocationNumber) and have it return a structure of some sort with all of the values you need to create the TextView back in MainActivity. You could create a helper method in MainActivity which takes the structure returned by doSun2() as an argument and returns a new TextView ready for adding to the Activity Layout.
In general, only Activities should create and manage any UI elements.
If DoSun really should be an Activity, then do not attempt to create an instance of it via it's constructors. Instead, create an Intent and use startActivity to create it.
All this said, you should get into the habit of describing what you want to achieve, since your approach (which I have responded to) may not be the right one.
Good luck!
Related
I need to create a login screen and a simple first screen (with a log out button). When a user logs in, for convenience, it does not require to log in again (only when the log out button is hit). To do this, i need to store a boolean variable whether the users is logged in or not.
When I hit the home button and open the app again, the app remembers that I already logged in. But when I hi the back button, it does not remember it.
Here is my code of the login screen:
package com.example.a20172425.login;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class LoginActivity extends AppCompatActivity {
EditText usernameEditText;
EditText passwordEditText;
TextView falseLoginTextView;
SharedPreferences pref;
boolean validCredentials = false;
public static Boolean login = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText = (EditText)findViewById(R.id.usernameField);
passwordEditText = (EditText)findViewById(R.id.passwordField);
falseLoginTextView = (TextView)findViewById(R.id.falseLoginText);
pref = getPreferences(MODE_PRIVATE);
login = getLoginStatus();
if(login) {
toMainActivity();
}
}
public void checkCredentials(View v){
//clear possible previous content
falseLoginTextView.setText("");
//retrieve username and password
String username = usernameEditText.getText().toString();
String password = passwordEditText.getText().toString();
if ((username.equals("username")) && (password.equals("password"))) {
validCredentials = true;
setLoginStatus(true);
//setUsername(username);
} else if ((username.equals("a")) && (password.equals("a"))) {
validCredentials = true;
setLoginStatus(true);
//setUsername(username);
}
if (validCredentials){
toMainActivity();
}
else
{
falseLoginTextView.setText("Incorrect username and or password");
}
}
public void toMainActivity(){
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("Username", usernameEditText.getText().toString());
this.startActivity(intent);
//makes sure pressing the back button does not send the app back to the login screen
this.finish();
}
// gets the logged_in value from persistent memory.
public Boolean getLoginStatus (){
return pref.getBoolean("Logged_in",false);
}
//sets the logged_in boolean value in persistent memory.
public void setLoginStatus(Boolean loginStatus){
//editor to change values to be stored in memory
SharedPreferences.Editor edit = pref.edit();
edit.putBoolean("Logged_in",loginStatus);
//save changes
edit.commit();
}
}
This is my code of the simple first screen:
package com.example.a20172425.login;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import static com.example.a20172425.login.LoginActivity.login;
public class MainActivity extends AppCompatActivity {
TextView LoginTextView;
LoginActivity loginActivity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoginTextView = (TextView) findViewById(R.id.LoginTV);
String username = getIntent().getStringExtra("Username");
LoginTextView.setText("Currently logged in as: " + username);
loginActivity = new LoginActivity();
}
public void toLoginActivity(View v) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
this.startActivity(intent);
login = false;
//loginActivity.setLogin(false);
//makes sure pressing the back button does not send the app back to the login screen
this.finish();
}
}
Any suggestion will be appreciated.
EDIT: I write Kotlin in my day to day job, I didn't actually compile the Java examples below so there may be some syntactical errors. However, it should be fairly trivial to resolve these with basic working Java knowledge. The concepts in this answer are applicable to the vast majority of OO languages (Kotlin, Java, C# etc.).
I'm updating this answer to give some more detail on what an interface is, why they are useful, how callbacks work and how they are implemented under the hood.
In object oriented programming (OO) and, in this case, Java; there is a type system that allows for polymorphism. Polymorphism, when broken down, means (poly -> many) and (morphism -> behaving like), or, in other words, many similarly behaving different types.
What these means in more concrete coding terms is that you can have many different classes of types which conform to a common behaviour (or interface). The behaviour of a type should be thought of as it's outwardly observable behaviours and not the internal implementation. It is useful to conceptualise this with respect to the type system. For example, a behaviour is defined as a transformation from one type to another (for instance a function that takes a collection of strings and returns a string). There are many functions that could perform this transformation, but the outwardly observable behaviour of all of these functions is the same (in other words, a transformation Collection -> String).
It therefore follows that such a type system can allow for arbitrary swapping of implementations as long as the outwardly observable behaviour is maintained.
Interfaces are a popular language construct to achieve this. An interface merely defines the tranformations between types and gives them names. Other types may then depend on this interface and call methods of this interface without any concern as to the actual implementation of the methods (the only constraint being that the implementors of said interface must conform to the type transformations - this is enforced at compile time in Java).
Here is a very simple interface:
public interface Car {
public Int accelerate(Int force);
public Int steer(Int direction);
}
I use the car example as it's quite intuitive. Here we can see two type transformations, from Int -> Int with a name accelerate, and from Int -> Int with a name of steer.
All cars can accelerate and steer. But not all cars accelerate and steer in the same way. However, all cars steer and accelerate behaviours follow a common pattern (or type transformation). They take some input value and result in some output value.
So, we could provide several implementations of car like so (bear in mind this is a very contrived example, so don't judge):
public class Ford implements Car {
#Override
public Int accelerate(Int force) {
return force * 1;
}
#Override
public Int steer(Int direction) {
return direction * 1;
}
}
public class Ferrari implements Car {
#Override
public Int accelerate(Int force) {
return force * 10;
}
#Override
public Int steer(Int direction) {
return direction * 10;
}
}
As you can see, a Ford and Ferrari both steer and accelerate. But the Ferrari does it differently (but it still conforms to the type transformation just as the Ford does).
Now, here we introduce polymorphism, which is a very powerful tool. Imagine we have the following class:
public class Person {
private Car car;
public Person(Car car) {
this.car = car
}
}
So, a person can be constructed by passing a car as a dependancy to it. Due to polymorphism we can pass any instance of an object that implements (or conforms to) the Car interface. For instance, we could do the following:
public class Main {
public void main([String] args) {
Person poorPerson = new Person(new Ford());
Person richPerson = new Person(new Ferrari());
}
}
Pretty nifty! Now we can create hundreds of different types of cars but our person class never has to change! Our person class can call methods on their respectively owned cars and never have to worry about anything breaking (because all cars can accelerate and steer).
So, how does this relate to the original question? Let us consider this very contrived example of an Android View class and a Callback interface:
public interface ContrivedCallback {
public void onClick();
}
public class ContrivedView {
private ContrivedCallback callback;
public void setOnClickListener(ContrivedCallback: callback) {
this.callback = callback;
}
private void onClick() {
this.callback.invoke();
}
}
Let us assume that the onClick method in the ContrivedView class is magically called by the Android OS when the view is clicked. Now, when the view is clicked, the callback (if set) is invoked. But, as we now know, the callback is just an interface, so whatever implementation was provided to the setCallback method will be invoked.
So, the callbacks single defined method is merely a transformation from Void -> Void (in other words, it takes no arguments and returns no value). It's just some code to run. The implementation may launch rockets, save to a database, print a string or do literally nothing, it's up to the coder providing the implementation).
I hope this makes sense? Now, with respect to the original question:
You can use an onClickListener callback. In this callback implementation you can write some code that updates some state of the Activity or Fragment (or write to preferences or local database, or launch missiles... you get the picture).
You create an implementation and then assign this implementation to the callback listener on the button in question like so (in your onCreate method):
logoutButton = (Button)findViewById(R.id.logoutButton);
logoutButton.addOnClickListener(class callback extends DialogInterface.OnClickListener {
#Override
public void onClick() {
// Do stuff here...
}
});
I must write a program with android which can find ssid and show it. My problem is how can i make a relation between an image button in first page and an activity or function in other page.
Buy the way i'm beginner and download the code of searching method because of that i can not recognize which one is the main method or function for pass it to setonclick method that i write for image button in first page?
please answer as soon as you can i need it immediately.
If you are trying to call another activity's method from your existing activity then you should use these steps.
First save the context or instance of the callee activity; for this you can use a class that holds your global data. In this class make the object of this activity.
FirstActivity first = null;
When the callee activity is first created, initialize this instance.
public void setFirstActivity(FirstActivity factivity)
{
first = factivity;
}
And when you do need to call this callee activity's method then access this instance from this global class and with the help of this instance, you will have access to the methods of the callee activity.
public FirstActivity getFirstActivity() {
return first ;
}
use it to get access to the methods or instances of the activity.
Click on the ImageButton, and add the name of the function in the On Click property (Simply the name, like myFunction)
In your code, copy-paste this function and replacemyFunction by the name of the function you chosed
public void myFunction(View v)
{
String ssid = ((EditText)findViewById(R.id.EditTextID)).getText().ToString();
Intent intent = new Intent(this, SecondView.class);
intent.putExtra("SSID_KEY", ssid);
startActivity(intent);
}
And replace SecondView by the class that displays your second page and EditTextName by the ID of your EditText.
In the OnCreate function of your second class, you can get your ssid using the following code
#Override
protected void onCreate(Bundle savedInstanceState) {
String ssid = getIntent().getStringExtra("SSID_KEY");
//Do other work here.
}
Also, on top of the class containing the ImageView, don't forget to add these lines:
import android.view.View;
import android.widget.EditText;
I know that I can pass some values between Activities using intent.
However, if I want to pass whole Activity to another Activity I think it is not good approach.
Is there another way to do that?
I have Settings Activity in which I am changing some Colors. So after I come back to my Main Activity I would like to apply those colors. To do this, I need access to MainActivity fields after I change Color value, so inside PreferenceActivity. In other words, I want to have access to Main activity fields from PreferenceActivity class. Any ideas?
You should be using a SharedPreference and then accessing that in your main activity. I recommend you reading up at http://developer.android.com/guide/topics/ui/settings.html because it seems like you are implementing your settings activity incorrectly. The part you might be specifically interested in is the "Read Preferences" section. However, I strongly suggest you read through the whole thing and then implement your settings the proper way.
Updated answer with the 3 different ways (that I can think of):
1) Start your preference activity using startActivityForResult(), then in your onActivityResult() access the SharedPreference and make your necessary changes. See here
2) Register a SharedPreferenceChangeListener with your MainActivity, which will be called when any changes happen to your SharedPreference. See here for a detailed discussion. Also see my initial response.
3) In your MainActivity's onResume(), access the SharedPreference and then make your changes there. I do not like this method because you will be cluttering onResume() with more logic and you will also probably have to have a variable that keeps track of the state of the variable you are interested in.
I would personally go with option 2 because the callback was created for this exact purpose.
I think you could pass the value by using method putExtra(name, value).
And after you start new activity you can get the value you pass before by using method getStringExtra(name).
Shared preferences can be used. If you want your changes to be reflected right away add listener. Refer to SharedPreferences.onSharedPreferenceChangeListener. Its an easy way to do.
If you want to lots of changes required in many activity from you change in any one.
And access last modify data from all Activity and modify also.
for example.
Constants.java
public class Constants
{
public static String name;
}
In your MainActivity you have an editText.
MainActivity.java
public class MainActivity extends Activity {
private EditText yourName;
private Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourName = (EditText) findViewById(R.id.yourName);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Constants.name = yourname.getText().toString();
Intent intent = new Intent(getApplicationContext(),Activity2.class);
startActivity(intent);
}
});
}
In your Activity2 you have an TextView and that getting value which you enter in MainActivity.java without pass in Intent.
Activity2.java
public class Activity2 extends Activity {
private TextView yourName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourName = (TextView) findViewById(R.id.tv_yourName);
// directly use ferom serializable class
yourname.setText(Constants.name);
}
like that you use many values from all activity and modify from all activity.
im trying to run this simple code (im a beginner :).
trying to run this. the // text is usually what i use for buttons. however, i saw this switch technique that i wanted to try, it seemed more efficient. however, i get errors related to the onClick (something about the ( ) and that 'void is an invalid type'). i have no idea what can cause this. just wanna access the buttons. can anyone please tell me why?
Thanks!
package com.experiment.fewops;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class FewOptions extends Activity {
/** Called when the activity is first created. */
final Button sexy = (Button) findViewById(R.id.buttonSexy);
final Button text = (Button) findViewById(R.id.buttonText);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// sexy.setOnClickListener(new View.OnClickListener() {
//
// #Override
// public void onClick(View v) {
// Intent intent = new Intent(this, SexyPage.class);
// startActivity(intent);
// }
// });
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.buttonSexy:
Intent intent = new Intent(this,SexyPage.class);
startActivity(intent);
break;
}
};
}
}
There are actually 2 problems here:
First, as #Saiesh said, if you want to implement the click listener at the class level, you need to change your class declaration to implment OnClickListener. So your declaration will look like
public class FewOptions extends Activity implements OnClickListener{
The second problem (and the reason you're getting the error about void being a bad type) is that you're declaring the onClick method in the body of your onCreate method. move the declaration of the onClick method outside the closing brace (}) of the onCreate method and that error should go away.
One more note: after you make the 2 fixes above, don't forget to add your class as the click listener for the button:
sexy.setOnClickListener(this);
You need to pass right context
Intent intent = new Intent(FewOptions.this,SexyPage.class);
FewOptions.this.startActivity(intent);
Well the solution is that to use this onClick() method your class needs to implement the onClickListener interface . Thus your class heading should be something like this
public class FewOptions extends Activity implements onClickListener
{
//Eclipse will automatically ask you to override the onClick() method
}
So thats the solution :)
public class Menu extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
//myIntent.setClassName("hello.World", "hello.World.mybuttonclick");
// myIntent.putExtra("com.android.samples.SpecialValue", "Hello, Joe!"); // key/value pair, where key needs current package prefix.
//startActivity(myIntent);
//Button myButton = (Button) findViewById(R.id.my_button);
super.onCreate(icicle);
setContentView(R.layout.main);
}
public void updateLayout(){
Intent myIntent = new Intent(Menu.this, mybuttonclick.class);
startActivity(myIntent);
// TextView sayHello = (TextView) findViewById(R.id.Hello);
}
}
Hey guys, I am a new android java student and we have to develop a simple hello world app.. I am finding some difficulty getting my onClick() activity to work, using android:Onclick in xml.. what i am trying to do is change the content view do display a simply a different layout and saying hello.. i am using setContentLayout to do this, every time i click said button tho the android app crashes out.. am i doing something wrong?
regards,
Stefan
When you set a click listener in xml you must have the method defined inside the activity you are clicking in. Lets say you set the onClick in xml to be "buttonClicked", you must create a method looking exactly like the one below.
public void buttonClicked(View view)
{
//Your code here
}
The thing to notice is that the method is a public void with only a single parameter of type View. XML defined click listeners must be like this to work. The view object in the example above is the view that was clicked.
You update layout function needs to read
public void updateLayout(View view)
In response to your question, there are a number of things that are issues causing the complication that you described. Let it first be said, that you don't have to do anything any particular way, provided that you make concessions for certain things. Android is a very flexible platform and Java, as an OOP language allows you to do things that many non OOP languages do not.
Whenever you create a "clickable" item, like a Button, if you want to have your program respond, you must have something "listen" to it. This is known as a Listener. In your case, you are looking for an OnClickListener. The OnClickListener does not have to be a part of the Activity necessarily. It just has to be a class that implements View.OnClickListener. Then, you have tell the setOnClickListener() method of the Button who its listener is. The following example shows what is necessary without your declaration in XML (but it is important).
class Menu extends Activity implements View.OnClickListener
{
public void onCreate(Bundle icicle)
{ setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.BUTTON_ID_AS_DEFINED_BY_YOUR_XML);
btn.setOnClickListener(this);
}
public void onClick(View view)
{ int id = view.getId();
if (id == R.id.BUTTON_ID_AS_DEFINED_BY_YOUR_XML)
updateLayout()//Do your Click event here
}
public void updateLayout()
{ //updateLayout code...
}
}
Something that needs to be noted is the OnClick() above. Every OnClickListener must use the same signature as theOnClick() That means itmust have the same return and same arguments even if it has a different name. For what you are trying to do (in XML), you have set your android:OnClick to updateLayout. This means that `updateLayout() must be declared as follows:
public void updateLayout(View view)
Now, getting the update method to actually work: While you provide your code, we don't actually know what errors you are getting. It is always much easier to solve a problem if we have a copy of the Logcat output that includes the error you are receiving. Once, we have that we can target your error specifically and I can edit my answer to include what you may additionally need.
FuzzicalLogic