Button Onclick Listener in included layouts

I come to you on bended knee, question in hand. I am relatively new to Android, so pardon any sacrilegious things I might say.

Intro: I have several layouts in the app, that all have to include a common footer. This footer has some essential buttons for returning to the home page, logging out, etc.

  • Encoding and muxing video using MediaCodec and MediaMuxer
  • Shared Element Transitions Between Views (not Activities or Fragments)
  • How to programmatically populate Reminders section on Android device's Calendar app?
  • ADB server version (36) doesn't match this client (39) {Not using Genymotion}
  • Is main thread the same as UI thread?
  • Cannot resolve constructor ArrayAdapter
  • I managed to get this footer to appear in all the requisite pages with the help of the Include and Merge tags. The issue lies in defining on click listeners for all the buttons. Although I can define the listeners in every activity associated with screens that include the footer layout, I find that this becomes terribly tedious when the number of screens increases.

    My question is this: Can I define a button click listener that will work across the application, which can be accessed from any screen with the use of the android:onClick attribute of the Button?

    That is to say, I would like to define the button click listener once, in a separate class, say FooterClickListeners, and simply name that class as the listener class for any button clicks on the footer. The idea is to make a single point of access for the listener code, so that any and all changes to said listeners will reflect throughout the application.

    Related posts:

    How do I jump to XML resources in Eclipse instead of R.java
    notifydataSetChanged on Adapter will update with new items, but will not update the existing items
    How to turn screen on during partial wake lock
    Sugar ORM just won't create tables
    Android Custom ProgressBar not Rotating
    libgdx doesn't render fonts properly after resume
  • Refer to ActionBarSherlock from a library
  • How does CursorLoader with LoaderManager know to send the cursor to a CursorAdapter?
  • how to calculate exact foot step count using accelerometer in android?
  • Taking pictures on Android from Delphi Firemonkey XE5 app
  • Using tesseract on android
  • Take screenshot
  • 3 Solutions collect form web for “Button Onclick Listener in included layouts”

    I had the same problem with a menu which I used in several layouts. I solved the problem by inflating the layout xml file in a class extending RelativeLayout where I then defined the onClickListener. Afterwards I included the class in each layout requiring the menu. The code looked like this:

    menu.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <ImageButton android:id="@+id/map_view"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:src="@drawable/button_menu_map_view"
            android:background="@null"
            android:scaleType="fitCenter"
            android:layout_height="@dimen/icon_size"
            android:layout_width="@dimen/icon_size">
        </ImageButton>
    
        <ImageButton android:id="@+id/live_view"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:src="@drawable/button_menu_live_view"
            android:background="@null"
            android:scaleType="fitCenter"
            android:layout_height="@dimen/icon_size"
            android:layout_width="@dimen/icon_size">
        </ImageButton>
    
        <ImageButton android:id="@+id/screenshot"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:src="@drawable/button_menu_screenshot"
            android:background="@null"
            android:scaleType="fitCenter"
            android:layout_height="@dimen/icon_size"
            android:layout_width="@dimen/icon_size">
        </ImageButton>
    
    </merge>
    

    MenuView.java

    public class MenuView extends RelativeLayout {
    
        private LayoutInflater inflater;
    
        public MenuView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(R.layout.menu, this, true);
    
            ((ImageButton)this.findViewById(R.id.screenshot)).setOnClickListener(screenshotOnClickListener);        
            ((ImageButton)this.findViewById(R.id.live_view)).setOnClickListener(liveViewOnClickListener);       
            ((ImageButton)this.findViewById(R.id.map_view)).setOnClickListener(mapViewOnClickListener);
        }
    
        private OnClickListener screenshotOnClickListener = new OnClickListener() {
            public void onClick(View v) {
                getContext().startActivity(new Intent(getContext(), ScreenshotActivity.class));
            }
        };  
    
        private OnClickListener liveViewOnClickListener = new OnClickListener() {
            public void onClick(View v) {
                getContext().startActivity(new Intent(getContext(), LiveViewActivity.class));
            }
        };
    
        private OnClickListener mapViewOnClickListener = new OnClickListener() {
            public void onClick(View v) {
                getContext().startActivity(new Intent(getContext(), MapViewActivity.class));
            }
        };  
    }
    

    layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <SurfaceView android:id="@+id/surface"
            android:layout_width="fill_parent"
            android:layout_weight="1"
            android:layout_height="fill_parent">
    
        </SurfaceView>
    
        <!-- some more tags... -->
    
        <com.example.inflating.MenuView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" />
    
    </RelativeLayout>
    

    with the <com.example.inflating.MenuView /> tag, you are now able to reuse your selfwritten Layout (incl onClickListener) in other layouts.

    This is something that is getting added to roboguice in the near the future. It will allow you to build controller classes for things like titlebar’s and footers and have the events autowired for you.

    Checkout http://code.google.com/r/adamtybor-roboguice/ for the initial spike.

    Basically if you are using roboguice you can define a component for footer and just inject that footer component into each activity.

    Unfortunately you still have to add the controller to every activity, just like you did with the include layout, but the good news is everything gets wired up for you and all your logic stays in a single class.

    Below is some pseudo code of some example usage.

    public class FooterController {
      @InjectView(R.id.footer_button) Button button;
    
      @Inject Activity context;
    
      @ContextObserver
      public void onViewsInjected() {
        button.setOnClickListener(new OnClickListener() {
           void onClick() {
             Toast.makeToast(context, "My button was clicked", Toast.DURATION_SHORT).show();
            }
        });
      }
    }
    
    public class MyActivity1 extends RoboActivity {
      @Inject FooterController footer;
    }
    
    public class MyActivity2 extends RoboActivity {
      @Inject FooterController footer;
    }
    

    The solution as you describe is impossible, sorry. But you can have common parent activity for all your activities that use the footer. In the activity just provide handler methods for your footer buttons, then just inherit from it every time you need to handle the footer actions.

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.