Common buttons onClick for every activity in android - android

My layout contain one header in which i inculded in each Activity, in this header there is a image button. Is it possible to write a common onClick event for this imageButton??

You can write a class that extends OnClickListener and the onClick method. Then in each activity's onCreate method, find the ImageButton and set its onClickListener to that class:
MyOnclickListener implements OnClickListener {
private Context context;
public MyOnclickListener(Context context) {
this.context = context;
}
#Override
public void onClick(View arg0) {
Intent intent = new Intent(context, MyActivity.class);
context.startActivity(intent);
}
}
In your activities:
protected void onCreate(...) {
setContentView(...);
((ImageButton) findViewById(R.id.mybutton)).setOnClickListener(new MyOnclickListener(this));
}
EDIT: Sorry, of course implements.
EDIT2: See updated code for Context reference.

Yes. Create a singleton class that implements the required listener and add that instance to the button on each screen.

The answers provided by cant0na and Juhani are most likely the answers you are looking for (with a small note on cant0na's answer). If you need a more self-maintained and fault tolerant solution you can define your very own "widget" which handles its own events. For this you'll need:
A xml-layout file which will describe your header.
A custom class which will (automatically) inflate the above XML layout and manage any "common events".
The benefit of this solution is that you don't have to add a new instance of your common OnClickListener in each and every activity which will show your header. You simply add your header to your activitys layout-XML (see example code below) and nothing else. Foolproof. You also get a more "decoupled" code this way (your header doesn't depend on any implementation specifics of your application and its activities).
The drawback is that it's a more complex solution and it might seem a bit over-kill for small projects. It's also a bit tricky to keep this solution "decoupled" if you want to do any activity specific actions on the button click. You might want to consider "default behaviour" in combination with "code injection" in the MyHeader class. The code injection would then require further manipulation on the header class (inject the onClick implementation) in the activities which deviates from the default behaviour.
Example header.xml
<com.dbm.widget.MyHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="60dp"
android:layout_height="20dp"
android:src="#drawable/myIcon"
android:id="#+id/myButton" />
</com.dbm.widget.MyHeader>
Example MyHeader.java
package com.dbm.widget;
public class MyHeader extends LinearLayout implements OnClickListener {
// Constructor.
public MyButton() {
((ImageButton) findViewById(R.id.myButton)).setOnClickListener(this);
}
// OnClick event callback.
public void onClick(View view) {
// Do whatever you need to do here.
}
}
Example activity.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.dbm.MyHeader
android:layout_width="match_parent"
android:layout_height="20dp" />
<!-- Your other content goes here -->
</LinearLayout>

Related

Android Studio Master Detail List onClick not working

I am new to android development so may be i am missing something elementary here, but after almost 2 days of googling I am still unable to figure out the cause.
I have followed the following article to create my project, except that I am invoking this activity from another activity when a button is clicked.
I have also created my own List adopter public class MyListAdapter extends ArrayAdapter<MyData> and in the getView() method of this adapter I am actually providing a different representation like below.
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view, parent, false);
}
this all works fine I am able to bind the data and its displaying the results on the list without any issues. Now I want to show the details of selected MyData when the user clicks on the list item, but this is just not working no matter what I try.
I have ensured that my activity is implementing the callback interface like below:
public class MyItemListActivity extends FragmentActivity
implements MyItemListFragment.Callbacks
and the callback itself is also very simple:
public interface Callbacks {
public void onItemSelected(MyData item);
}
also on my MyItemListFragment the onAttched is correctly hooked up mCallbacks = (Callbacks) activity;
What I really notice is that the following function is just not called when I click on the list item:
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
MyData data = DataContent.ITEMS.get(position);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(data);
}
my fragment that displays the list item looks like this:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myitem_list"
android:name="path.MyItemListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context="path.MyItemListActivity"
tools:layout="#android:layout/list_content" />
and the actual custom adapter view my_list_view looks like below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >....</RelativeLayout>
I can see that its missing the android:onClick tag here, but not sure if that is the cause and also who needs to implement this handler as there is no direct context on this layout.
Any help is really appreciated.
Regards
Kiran

Android - Custom views can bind to their own listeners by not specifying an ID - doesn't work

I follow butterknife instruction, as they said: "Custom views can bind to their own listeners by not specifying an ID."
Grade
Gradle
compile 'com.jakewharton:butterknife:7.0.0'
I create a BaseButton:
public class BaseButton extends Button {
public BaseButton(Context context) {
super(context);
}
public BaseButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
#OnClick
public void onClick() {
System.out.println("Hello");
}}
activity_main
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<com.example.BaseButton
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"/>
And MainActivity
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
// #OnClick(R.id.button)
// public void buttonPressed(){
// System.out.println("buttonPressed");
// }
}
If I un-comment buttonPressed method, "buttonPressed" shows up. When I comment, nothing happens. What I expect is to see "hello" first and then "buttonPressed".
Do you have any ideas? Thank you.
There's two problems here:
The view never calls ButterKnife.bind(this) to bind the click listener to itself. Without this, there's no way of knowing when to attach the listener. The call in the your activity does not implicitly bind the view to itself.
If you put an #OnClick for the button in your activity and an #OnClick for the button inside of itself one of them is going to overwrite the other. Butter Knife is just creating a click listener and calling setOnClickListener on the view. Since you'd have two, one will simply replace the other and you'll stop seeing the log line for whichever called bind first.

onClick attribute in XML linking to method in Activity class

There are quite a few questions about this subject, but could not find any with the specific problem I have...
In my layout.xml, I use the android:onClick tag for a Button to call the right onClickListener. I get the error :
java.lang.IllegalStateException: Could not find a method handle_cancel(View) in the activity class com.matthieu.HelloWorldApplication for onClick handler on view class android.widget.Button with id 'button_cancel'
I have that method implemented in the Activity, but it is looking for it in the class that extends Application... I don't understand why. The View and all that is setup only in the Activity.
If anyone needs, here is the declaration of that method (in my activity, NOT in HelloWorldApplication):
public void handle_cancel(View v) {
// do something useful here
}
Edit (from adamp request)... and probably answering my own question :
Here is part of the code where that layout is used...
public class AddVocabularyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.top); // that layout contains an empty LinearLayout id/main_content
}
private some_other_function() {
LinearLayout main_content = (LinearLayout) findViewById(R.id.main_content);
main_content.removeAllViews();
View.inflate(getApplicationContext(), R.layout.hello, main_content); // layout.hello is the one containing the button
}
// some other stuff
}
While copy/paste this code, I am guessing the problem is that I used getApplicationContext to inflate the View with that Button...
As mentioned in my edit, changing the getApplicationContext() with the Activity context fixes it...
The convention works like this:
In the layout xml file, you give this attribute:
android:onClick:"methodname"
Then, inside a class, you define a method like this:
public void methodname(View v){
//your method code
}
Any other way of doing this is not documented. If you need parameters, just call another method inside that method.

Adding a custom view to XML... but with a GENERIC-type

I am working on a custom view with a hope of reusability. It should have a generic type, like this:
public class CustomViewFlipper<someType> extends ViewFlipper { }
I know how to bind a normal custom view to the XML file. But I couldn't find any example for this situation. Is there any way to define a generic type for a class in XML?
As type parameters are actually cleared off in bytecode, you can use in XML the class name as if it was not parametrized and then cast it to proper parametrized type in java code.
consider having class:
public class CustomViewFlipper<T extends View> extends ViewFlipper {
//...
and in your activities layout xml:
<view
class="com.some.package.CustomViewFlipper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/customFlipper"/>
then in your activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
#SuppressWarnings("unchecked")
CustomViewFlipper<TextView> customFlipper =
(CustomViewFlipper<TextView>) findViewById(R.id.customFlipper);
I don't think so, but you can create your own subclass:
public class TheClassYouPutInTheLayoutFile extends CustomViewFlipper<someType>
and use that class in your layout XML.
I use this approach and it works for me.
<com.some.package.CustomViewFlipper
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/customFlipper"/>
And then in the activity, instantiate as below
CustomViewFlipper<someType> customFlipper =
(CustomViewFlipper<someType>) findViewById(R.id.customFlipper)

Custom widget throws a NullPointerException on setRequestedViewSize

Good morning folks,
I'm working on an Android app and I've run into a bit of a problem. I have created a new class that extends View. I have overridden the appropriate methods (the Constructor, onDraw, onMeasure) and am instantiating the View through the applications layout XML (which is called main.xml).
Within the source code of my app I have the following code:
public class CustomViewTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* I *think* I need to setContentView before I actually can use any of the widgets on the form. */
setContentView(R.layout.main);
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// my new widget
newWidget s = (newWidget)findViewById(R.id.testWidget);
s.setRequestedViewSize(300);
}
});
}
}
the problem here, is that s.setRequestedViewSize(300) throws a NullPointerException. Has anyone run into this before or can lend me some advice?
[EDIT]
The main.XML looks like this:
It returning null, but the XML looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.testing.CustomViewTest02.newWidget
android:id="#+id/testWidget"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<Button android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></Button>
</LinearLayout>
Thanks you!
Sam
The problem was in my widget, I had the correct constructor (Context context AttributeSet attr); HOWEVER - super(context) was being called - not super(context, attr). Once I fixed that, life was better.
Thanks for the info everyone!
You have no view with the R.id.testWidget ID: it's not about nonstatic methods. Since findViewById() returns null, the next line throws an exception.
Do you reference your custom view inside your main.xml? #Pontus is right. There is no View being returned from the findViewById() method.
It would probably be better to get your reference to it in the onCreate method (call the constructor there if necessary) and then set it visible or add it to another view (whatever you are trying to do with it) once the button is clicked.
EDIT: Based on your XML above. Does your custom class implement a constructor that takes a Context and an AttributeSet? The constructor with the AttributeSet is the constructor that Android will call to create your class from the XML layout.

Categories

Resources