Android: onClick callback with additional parameter? - android

Starting from this
<Button
android:onClick="onBtnClicked"
android:id="#+id/btn_edit_shared_preferences"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/btn_show_map"
android:layout_centerHorizontal="true"
android:text="Edit Shared Preferences" />
Here says that the only parameter send to the onClick callback function is the View object.
Well, I might need some "extra-parameter", like in this case: I have a function that handles the lauching of activities, so it would be
openActivity(View v){..}
On the other hand, in the layout I would like to have
:onclick="openActivity(activityClassName)"
What is the right way to do something similar to this?

You can use android:tag="YouActivity" along with your android:onClick="openActivity"
now you can have Activity name in your openActivity() like this:
void openActivity(View v)
{
String activityName = v.getTag().toString();
Class<?> aClass = null;
try {
aClass = Class.forName("your.package."+activityName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
startActivity(new Intent(this, aClass));
}

Well, the View object only parameter which the onClick event gets but you can get more information through the Context object.

A single button can correspond to a single method. There is no way to pass through extra paramaters. For example, in your case, you want the button to launch an activity. One way to do that is to write a method just for launching that activity.
<Button
android:onClick="launchPreferencesActivity"
android:id="#+id/btn_edit_shared_preferences"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/btn_show_map"
android:layout_centerHorizontal="true"
android:text="Edit Shared Preferences" />
Then in your Activity:
public void launchPreferencesActivity(View v){
//start Activity
}
Different buttons can correspond to different methods to handle the click event. Or if you want, you can use the View parameter to distinguish what view is calling the method and handle it that way.
If there is some other factor going on that might change the behavior of the button, you can always change the onClickListener in code. But generally, I would think the above approach works better for what your are trying to do.

Related

How setting Clickable attribute in XML works?

I have a Button in an Activity:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test"
android:onClick="onClickEvent"
android:clickable="false"
android:focusable="false" />
and a method:
public void onClickEvent(View view) {
Toast.makeText(this, "Hey!!", Toast.LENGTH_SHORT).show();
}
In spite of setting clickable attribute to false in xml, why click event still should work?
does something overrides it?
In spite of setting clickable to false, why click event should work?
setClickListener resets that flag.
public void More ...setOnClickListener(OnClickListener l) {
2318 if (!isClickable()) {
2319 setClickable(true);
2320 }
2321 mOnClickListener = l;
2322 }
and yes android:onClick="onClickEvent" calls internally setOnClickListener
According to the most upvoted answer here, clickable goes back to true because of the global setOnClickListener method.
Cannot test at the moment, but maybe you could create two separate listeners and switch the one currently used by the button when you need it. So you can switch to a listener that does nothing when you want to disable clicking on it.
Looks a bit overkill to me, and the cleanest method is to use setEnabled(false) in my opinion, but try playing around with listeners if you really don't want to use setEnabled.

Can you reuse a fragment in multiple activities but with different functionalities?

Say I have a fragment that has three buttons and I want to reuse it for at least three activities, but I want those buttons to do different things for each activity. For example, in ActivityA, I want button1 to open Google Maps while in ActivityB, button1 goes to the music player. Is this possible or even the right way?
Of course you can. Just create an interface for the Fragment, let's say FragmentCallback, with your desired callback method, onButtonClick() for instance. In the onAttached() of your Fragment, cast the Activity to your new interface and store it in a variable private FragmentCallback callback;. Each Activity using this Fragment must implement this callback interface. Then call the callbacks onButtonClick() method in your Fragments onButtonClick() method. That's it - a very common pattern.
Yes you can, but you have to add more logic to your fragments and add some interfaces for each activity.
I don't recommend to do that, maybe you could reuse your layouts.
Is this possible?
It definetely is. You could just check which Activity is hosting your Fragment instance:
private void button1OnClick(){
/* could also use instanceof, BUT: if you have something like ActivityC extends ActivityA
then instanceof would evaluate to true for both */
if(getActivity().getClass().equals(ActivityA.class)) {
// do stuff
} else if(getActivity().getClass().equals(ActivityB.class)) {
// do another stuff
}
}
Is this the right way?
(attention opinionated answer)
It depends. If you have a complex and unique layout/functionality, I'd use different Fragments. If you have a simple layout with some buttons that just need to act differently in different Activities it is a good idea to reuse an existing Fragment class.
Yes you can!
if(getActivity() instanceOf ActivityA) {
//do stuff related to ActivityA
} else if(getActivity() instanceOf ActivityB) {
//do stuff related to ActivityB
}
Your activities have different logic, you can define the button logic in each of them and share the views in this way. You can use a fragment to accomplish this however you can be more direct by sharing a partial layout.
Create a partial layout called three_buttons.xml
three_buttons.xml
<LinearLayout>
<BUtton android:text="button 1"/>
<BUtton android:text="button 2"/>
<BUtton android:text="button 3"/>
</LinearLayout>
activity_a.xml
<LinearLayout>
<TextView android:text="I am A"/>
<include
android:id="#+id/three_buttons"
layout="#layout/three_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
activity_b.xml
<LinearLayout>
<TextView android:text="I am B"/>
<include
android:id="#+id/three_buttons"
layout="#layout/three_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

how to make a button redirect to another xml page

I'm making a button in xml, like this:
<Button
android:id="#+id/buttondp"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/thisisstringtext" />
and I want it to direct it to another page coded in xml. Can anyone help me out?
Make another activity and use
setContentView(R.layout.your_other_layout);
inside of it.
Then in the onClickListener for your button put this:
Intent i = new Intent(YourActivity.this, YourOtherActivity.class);
startActivity(i);
You can add the onclick listener to your button, so: android:onclick="method_in_your_activity".
In your activity added the method (method_in_your_activity) and add startActivity(NewActivity).
If you dynamically want to change the Content of your activity you can always call setContentView(my_layout) and change the content. However; its best practice to use another Activity.
You can use different activities for different layout. But if you want to use same activity for different layout then you should go for ViewFlipper . You can also get some animation when switching from one view to another. Tutorial regarding the same can be found here.
using this code in java file you will click button to redirect next page
public void onClick(View v)
{
Intent ia=new Intent(getApplicationContext(),second.class);
startActivity(ia);
}
In your button XML, add :
android:onCLick="myRedirectFunction"
In your MyMainActivity.java, add function named myRedirectFunction and inside that function :
Intent homepage = new Intent(MyMainActivity.this, MySubActivity.class);
startActivity(homepage);

Android, how to tell if user clicks a linkify link, or presses home button

I think I need to put some code within my onStop method. It pertains to a service that should be running only when the activity is finished()
but when the user follows some linkify'd text to the web browser, or when the user presses the homescreen, both call onStop() but these do not end the activity, I don't want to end the activity when a user follows a link, so I can't put finish() within onStop() unless I can detect and differentiate when this happens within onStop()
is there a way I can override Linkify() so that I can add a flag within it, or maybe make it run startActivityforResult() so that I can information back in a result?
similarly, is there a way I can set the activity to finish() when the user presses the home button?
Thanks
Is it possible for you to check isFinishing() in your onStop() to decide whether you need to run the service-related code or not?
#Override
protected void onStop() {
super.onStop();
if (isFinishing()) {
// Your service-related code here that should only run if finish()
// was called.
}
}
UPDATE: (after understanding the problem better)
Very similar to my suggested approach on another question, you can probably override startActivity() to intercept when the link is launching and set your flag if that's the case.
#Override
public void startActivity(Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_VIEW)) {
// maybe also check if getScheme() is 'http' then set our flag
persist.saveToPrefs("linkifyClick", true);
}
// proceed with normal handling by the framework
super.startActivity(intent);
}
That other answer also show how you can call startActivityForResult() too instead if you want.
SOLUTION (with still a remaining problem)
I put an onClick: attribute on my textView in the xml
<TextView
android:id="#+id/body"
android:paddingTop="10dp"
android:onClick="onTextViewClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
and then saved a flag within my sharedpreferences within that new method
public void onTextViewClick(View v){
//write to sharedpreferences
persist.saveToPrefs("linkifyClick", true);
}
and then in my onStop I can detect whether that flag is set or not!
#Override
public void onStop(){
super.onStop();
if(persist.getFromPrefs("linkifyClick", false) == false)
{
finish();
}
else
persist.saveToPrefs("linkifyClick", false); //if it was true, then set to false
}
PROBLEM
It is possible to click on the linkified text without touching the actual link portion. This sets the flag to true and still mixes up the lifecycle I am going for. So I need to be able to detect when the home button is pressed
UPDATE: this helped clarify the problem for the other poster (with the accepted answer), that person updated the answer and I accepted it after I put it in my code. It works.

Clickable TextView only works once

I made a textview clickable then it triggers an intent, it works but only once. After clicking the textview the first time it's no longer clickable and I have no idea why. Your help will be appreciated.
<TextView android:text="Click Me" android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="#+id/textView1"
android:textSize="50dp" android:focusable="false" android:longClickable="true"></TextView>
TextView txt = (TextView) findViewById(R.id.textView1);
txt.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(Example.this, Alert.class));
return false;
}
});
What does the alert class do? If it is an activity it could be that it is being laid over the top of your current activity so although you can see your activity, it's not at the top of the stack/in the foreground so you're not actually pressing the TextView, you're pressing a transparent activity that is over the top of it.
The easiest way to check that is to press the TextView, then press your device's back key and see if the TextView responds to the click.
Or are you sure you're not setting the same layout in Alert.class? That would make it look like it's the same activity but if the Alert class doesn't set the click listener, nothing is going to happen.
The fact that you're starting an activity with an intent and that's making an instance of another class (which I assume is also an activity) stops the click working to me is seriously suggesting that Alert is getting the click somehow instead of Example. When you say things work fine if you remove the intent backs that up as well. Maybe you could post the full source of both classes?
Do you have an onClickListener that disables the textview?
By returning false from onLongClick Android would also invoke the onClick listener if you have one.
Also you could try to remove android:focusable="false"

Categories

Resources