Android: Changing a textView from a standard java class outside an Activity - java

So I am curious if it is possible to change a TextView from another java class in Android.I know how to change it in the activity and have no issue doing that. But for reasons I am looking to pull out the UI changes into another file.
layout file
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Test UI"
android:textAlignment="center"
android:onClick="testUI"/>
<TextView
android:id="#+id/someText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SomeText"
android:textAlignment="center"/>
Here would be the code that I would have in the main activity
SetSomeText setSomeText = new SetSomeText();
public void testUI(View v){
setSomeText.Something();
}
Then I would have a standard java class that would allow me to change the TextView
public class SetSomeText extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_someNewActivity);
}
public void Something(){
TextView someNewText = findViewById(R.id.someText);
someNewText.setText("Something");
}
}
This ends up giving me an illegal state exception. I know this is not a normal way to do this. Just curious if something like this can be done.
java.lang.IllegalStateException: Could not execute method for android:onClick

Maybe you could do something like this in the class
public void Something(TextView myView){
myView.setText("Something");
}
And you can use it in main
MyClass class = new MyClass();
TextView someNewText = findViewById(R.id.someText);
class.Something(someNewText);

Use interface to communicate between activity and java class.
Steps to achieve this using interface.
Implement the interface in your activity.
Pass the instance of the interface to the java class.
With the help of the instance you can call the method which is implemented in your activity.
If you want to communicate between 2 different activities. Use startActivityForResult and setResult methods.

You shouldn't create an object of type Activity by your self you should start a new activity by using Intents
Only the Activity that created the view can Access it using
findViewById(int); ... so calling it from another activity (in SomeThing() function) would return null
If you wanted to make changes in a view using another class then you can do something like this :
public class myAwesomeClass {
TextView tv;
public myAwesomeClass(TextView v){
this.tv = v;
}
public void doSomething(){
tv.setText("This would work with no errors");
}
}
//and In the Activity class
myAwesomeClass mAC;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
mAC = new myAwesomeClass(findViewById(R.id.someText));
}
public void testUI(View v){
mAC.doSomething();
}
sorry for the bad writing .. Im using my phone :)

Related

Implementing a class that will override the onClick()

I want to create a method that, when implemented in other classes, you just need to pass some parameters and then call the - onclick() function to set the element.
At the moment, I´ve just done this. But this gives me a RunTimeException
Unable to start activity ComponentInfo{com.example.test/com.example.testActivity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
my code:
Class: clickeable
imports ...
public class ClickeableOptions implements View.OnClickListener{
private CardView cardView;
private Context cont;
private Class actTarget;
public OpcionesMainClickeables() {}
public ClickeableOptions(CardView cardView, Context cont, Class actTarget) {
this.cardView = cardView;
this.cont = cont;
this.actTarget= actTarget;
}
//Getters and Setters
#Override
public void onClick(View v) {
getCardView().setOnClickListener(this);
Intent intent = new Intent(this.getCont(), this.getActTarget());
startActivity(intent);
}
}
And i want to implement this class like this...
public class MainActivity extends AppCompatActivity{
private CardView cvRegistration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cvRegistration = (CardView) findViewById(R.id.cvRegistration);
ClickeableOptions optionRegistration = new ClickeableOptions(
cvRegistration, this, Registration.class
);
optionRegistration.onClick(optionRegistration.getCardView());
}
I've implemented the method in the same file, but I want to do it this way to keep things more tidy.
I think the problem is in the use of this, but i really don't get it
No need to call onClick explicitly from your Activity. Just try like below:
public ClickeableOptions(CardView cardView, Context cont, Class actTarget) {
this.cardView = cardView;
this.cont = cont;
this.actTarget= actTarget;
this.cardView.setOnClickListener(this);
}
And inside onClick
#Override
public void onClick(View v) {
Intent intent = new Intent(getCont(), getActTarget());
getCont().startActivity(intent);
}
And remove this line from Activity.
//optionRegistration.onClick(optionRegistration.getCardView());
Now when you clicked your CardView, Then Activity transitions start.
Try to replace this line:
startActivity(intent);
with
getCont().startActivity(intent);
Also, why are you inheriting ClickeableOptions from AppCompatActivity?
Although you have instantiated the ClickeableOptions (derived from Activity) object, none of its Activity life cycle methods have been called and none of the super class instantiation related work (normally should be done in onCreate) has been accomplished. Hence the ActivityThread is simply null and you've got an exception when invoking
startActivity(intent);
If you want to start another Activity on your CardView click then you need to
follow Leo Leontev's advice:
call
getCont().startActivity(intent)
instead of
startActivity(intent)
move the line
getCardView().setOnClickListener(this)
to the ClickeableOptions custom constructor's most bottom line
delete this line from your MainActivity$onCreate() method:
optionRegistration.onClick(optionRegistration.getCardView());
After all of above is done you'll be able to start new activity on click event.

How to use setOnClickListener to the buttons in android using java [duplicate]

I have trouble understanding this code. I get that findViewById will get the button widget and then it'll cast it. Then, it's going to use the button to call the setOnClickListener method. However, I don't know what is that argument being passed into the setOnClickListener and I have never seen code like that before. How is it that it creates a new object but is able to create a method of its own within another method's argument? Would be great if someone could explain that. Also, what type of object is the setOnClickListener method taking in?
btn = (Button)findViewById(R.id.firstButton);
btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
tv.setText(months[rand.nextInt(12)]);
tv.setTextColor(Color.rgb(rand.nextInt(255)+1, rand.nextInt(255)+1, rand.nextInt(255)+1));
}
});
It works like this. View.OnClickListenere is defined -
public interface OnClickListener {
void onClick(View v);
}
As far as we know you cannot instantiate an object OnClickListener, as it doesn't have a method implemented. So there are two ways you can go by - you can implement this interface which will override onClick method like this:
public class MyListener implements View.OnClickListener {
#Override
public void onClick (View v) {
// your code here;
}
}
But it's tedious to do it each time as you want to set a click listener. So in order to avoid this you can provide the implementation for the method on spot, just like in an example you gave.
setOnClickListener takes View.OnClickListener as its parameter.
This is the best way to implement Onclicklistener for many buttons in a row
implement View.onclicklistener.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
This is a button in the MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_submit = (Button) findViewById(R.id.submit);
bt_submit.setOnClickListener(this);
}
This is an override method
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.submit:
//action
break;
case R.id.secondbutton:
//action
break;
}
}
That what manual says about setOnClickListener method is:
public void setOnClickListener (View.OnClickListener l)
Added in API level 1 Register a callback to be invoked when this view
is clicked. If this view is not clickable, it becomes clickable.
Parameters
l View.OnClickListener: The callback that will run
And normally you have to use it like this
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
Take a look at this lesson as well Building a Simple Calculator using Android Studio.
its an implementation of anonymouse class object creation to give ease of writing less code and to save time
It works by same principle of anonymous inner class where we can instantiate an interface without actually defining a class :
Ref: https://www.geeksforgeeks.org/anonymous-inner-class-java/

How to define a specific layout onclick function globally for multiple activities

I need to define a layout for multiple activities in android and from the UI part, it is successful. But to code those elements to perform on each click listeners, I need to define it in all the java pages I use.
Can we globally define this in a java page and include it in the required pages?
menuButton = findViewById(R.id.menuButton);
menuButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(), MenuActivity.class);
startActivity(i);
finish();
overridePendingTransition(0, 0);
}
});
Yes and No.
You can create a BaseActivity which has the common logic that has to be executed for each button click.
But you need to implement the listener for the button on specific activity, since life cycle of each activity is independent of other activity.
To make the code readable better (avoiding implementing listener/setOnclickListener), you can use ButterKinfe, and create a method for OnClick() annotation, and call the method in BaseActivity.
What you essentially want to do is call the findViewById(), which can only be called if you have a reference to a Context variable. You should use your Activity Context, hence you pass this to the static function, which can then access all methods accessible via Context .
public class ExampleActivity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MenuUtils.setListener(this);
}
}
Define the static class like this:
public static class MenuUtils{
public static void setListener(Context context){
menuButton = context.findViewById(R.id.menuButton);
menuButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do stuff
}
});
}
}
What you should be careful about is that any Activity you pass to this function should have a menuButton in it's layout, otherwise you run the risk of getting a NullPointerException, which is when findViewById() cannot find menuButton.

In android, when is a context different from "this"?

I am at baby step level of programming on Android (and in Java in general). I do understand that Activity inherits from the Context class. However in every code snippet I have come across, every time a context must be mentionned, it is set to "this".
My question is : when is a context different from "this" ? Could you provide an real life example of context needing to be different from "this"?
Thank you very much.
Typically, you will want to use this when you are "inside" of an Activity. However, when you are using for example a Helper class, the reference this will not work. An example can be something like this:
public class MyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
}
A case, where you cannot:
public class MyHelper
{
/* some code of yours */
public void lockOrientation(Activity activity)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
}
The above code locks the orientation to the current orientation. Notice that you need to supply the method with an Activity parameter, since you cannot use:
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
In the first example, you could use this to achieve this, because you were "inside" of an Activity.
Another type of example, how do you set onClickListener.
First example, when you use this:
public class MyActivity extends Activity implements View.OnClickListener
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Button btn=(Button)findViewById(R.id.mybutton);
btn.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
//handle the click event
}
}
In this example, you can use this because in the first line, we wrote implements View.OnClickListener, so the class inherits from the given interface. Without the implements thingie, you couldn't do it. An example of setting the onClickListener without this:
public class MyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Button btn=(Button)findViewById(R.id.mybutton);
btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//handle the click event
}
});
}
}
In the second example, we are defining an Anonymous Inner Class, which will handle the click event of the button. Notice that in this case, our Activity does NOT implements View.OnClickListener.
In Outer Class you directly use "this" reference
In Inner Class Or Abstract Class implementation Or Interface implementation use "classname.this" reference
Example:
class Example{
int number = 0;
public Example(int number){
this.number = number;
}
}
notice that number in the contructor and number in the class are not the same. Altough they have the same name. Saying number = number doesn't make sense. Be using this you can asses number in the class.
For example when you are implementing an OnClickListener the "this" is different.
this is a reference to the current object — the object whose method or constructor is being called.
Inside an Activity's method this can be used as a Context object because Activity inherits from ContextThemeWrapper, which inherits from ContextWrapper, which inherits from Context.
A Fragment on the other hand does not inherit from Context. So to get the Context inside a Fragment you would have to call getActivity() for example.
This applies to any object you are calling this from.
Consider you are inside the OnClick() method of a View.OnClickListener and you want to start an Activity:
button.setOnClickListener (new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(this, NextActivity.class); // wrong because 'this' is the OnClickListener object
Intent intent = new Intent(CurrentActivity.this, NextActivity.class); // correct because 'this' is the CurrentActivity object
startActivity(intent);
}
});

add functionality to an onClickListener in a derived class

I've read many threads on how to create and handle Button clicks using onClickListener. However, I couldn't find anything that solved this problem.
I have a class myActivity and I would like to create a second class myExtendedActivity which extends myActivity by adding some extra functionality.
The class myActivity contains a lot of code which, for maintainability reasons, I don't want to duplicate. myExtendedActivity should behave exactly as myActivity with some extra function.
In particular in the onCreate method in myActivity I have the following code that add an onClickListener to my_button. The extended activity should just append a call to myExtraMethod.
myButton = (Button)findViewById(R.id.my_button);
myButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
[...] //a lot of code here
myExtraMethod();
}
});
Note that myExtraMethod simply broadcasts an Intent and it is not affected by any other part of the code in the Listener.
What I would like to do is to extend the OnClickListener in myExtendedActivity so that it first executes exactly the code written for myActivity and than myExtraMethod defined in myExtendedActivity.
I don't want to modify myActivity which should be completely unaware if myExtendedActivity is included in the project or not.
Thank you very much
Completely without modifying myActivity is barely possible.
You could use something like this in MyActivity (Some variant of the Template method pattern):
onCreate() {
myButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
myMethod();
}
});
}
protected void myMethod() {
[...] //a lot of code here
}
And then in MyExtendedActivty:
#Override
protected void myMethod() {
super.myMethod();
myExtraMethod();
}
If I understood your question right, the solution might be something like this:
In your layout for button you define the onClickListener from xml:
<Button
android:id="#+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="handleButtonClick"
/>
Then, in MyActivity you implement method:
public void handleClick(View view) {
}
And in MyExtendedActivity you override it:
public class MyExtendedActivity extends MyActivity {
#Override
public void handleClick(View view) {
super.handleClick(view);
//your code goes here
}
}
Without modifying myActivity, you can't because you're instantiating an anonymous class, and the subclass has no way to "hook in" to that anonymous class.
If you can modify myActivity, then you could make the anonymous class from myButton.setOnClickListener(...) a static class, and in your subclass extend the listener class calling super.onClick(v), followed by the functionality you expect.
Then add a method to get the correct listener
myButton.setOnClickListener(createMyButtonsListener())
that you can then override in the subclass providing the extended version.
Alternatively, add a method that can be overriden in a subclass (i.e. myExtraMethod()). that is called within your anonymous class.

Categories

Resources