Set OnClick Listener on Action Bar Title in Androi

2019-01-22 12:35发布

问题:

I am working on android application where I am using ActionBar so there one is navigation drawer icon to open it and title of ActionBar in ActionBar. I want to set a click listener on title of ActionBar such that it start a new Activity and set click listener different on navigation drawer icon to open navigation drawer menu.

I achieved a click on navigation drawer icon but when I click on title of ActionBar title also then it open the navigation drawer menu. Is there any way to set different click listener on title of ActionBar.

Thanks in advance.

回答1:

Try adding this code under the onCreate() function. This will grab the resource the action bar title is under, and assign it an id you can use to add an OnClickListener to. Let me know how it goes!

final int abTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
findViewById(abTitleId).setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
    //Do something
    }
});


回答2:

You could use a custom layout for the title and assign a listener to it:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ActionBar actionBar = getActionBar();
    if (actionBar != null) {
        // Disable the default and enable the custom
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayShowCustomEnabled(true);
        View customView = getLayoutInflater().inflate(R.layout.actionbar_title, null);
        // Get the textview of the title
        TextView customTitle = (TextView) customView.findViewById(R.id.actionbarTitle);


        // Change the font family (optional)
        customTitle.setTypeface(Typeface.MONOSPACE);
        // Set the on click listener for the title
        customTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.w("MainActivity", "ActionBar's title clicked.");
            }
        });
        // Apply the custom view
        actionBar.setCustomView(customView);
    }
}

actionbar_title.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <TextView
        android:id="@+id/actionbarTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:text="@string/app_name"/>

</LinearLayout>


回答3:

I think Simas's answer is the best one, but here's a hacky version in case you prefer that.

ViewTools.findActionBarTitle(getWindow().getDecorView()).setOnClickListener(...);

This one should be universal in that it works with:

  • stock Android ActionBar
  • Theme.AppCompat support ActionBar
  • v21-style setActionBar
    use <Toolbar android:id="@+id/action_bar"
    or pass in the inflated Toolbar as root
  • v21-style setSupportActionBar
    use <android.support.v7.widget.Toolbar android:id="@id/action_bar"
    or pass in the inflated Toolbar as root
  • custom Toolbar implementations may need a little adjustment,
    but then you could encapsulate this in that custom class.

Though I only tested with support:v22.

/** @param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
public static @Nullable View findActionBarTitle(@NonNull View root) {
    return findActionBarItem(root, "action_bar_title", "mTitleTextView");
}
/** @param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
public static @Nullable View findActionBarSubTitle(@NonNull View root) {
    return findActionBarItem(root, "action_bar_subtitle", "mSubtitleTextView");
}

private static @Nullable View findActionBarItem(@NonNull View root,
        @NonNull String resourceName, @NonNull String toolbarFieldName) {
    View result = findViewSupportOrAndroid(root, resourceName);

    if (result == null) {
        View actionBar = findViewSupportOrAndroid(root, "action_bar");
        if (actionBar != null) {
            result = reflectiveRead(actionBar, toolbarFieldName);
        }
    }
    if (result == null && root.getClass().getName().endsWith("widget.Toolbar")) {
        result = reflectiveRead(root, toolbarFieldName);
    }
    return result;
}

@SuppressWarnings("ConstantConditions")
private static @Nullable View findViewSupportOrAndroid(@NonNull View root, @NonNull String resourceName) {
    Context context = root.getContext();
    View result = null;
    if (result == null) {
        int supportID = context.getResources().getIdentifier(resourceName, "id", context.getPackageName());
        result = root.findViewById(supportID);
    }
    if (result == null) {
        int androidID = context.getResources().getIdentifier(resourceName, "id", "android");
        result = root.findViewById(androidID);
    }
    return result;
}

@SuppressWarnings("unchecked")
public static <T> @Nullable T reflectiveRead(@NonNull Object object, @NonNull String fieldName) {
    try {
        Field field = object.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        return (T)field.get(object);
    } catch (Exception ex) {
        Log.w("HACK", "Cannot read " + fieldName + " in " + object, ex);
    }
    return null;
}


回答4:

If you are using Toolbar with support v7:21. Check out the following code:

Field titleField = Toolbar.class.getDeclaredField("mTitleTextView");
        titleField.setAccessible(true);
        TextView barTitleView = (TextView) titleField.get(mToolbar);
        barTitleView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

            }
        });


回答5:

You can do this easily using Toolbar. Define toolbar in layout xml file as given below:

 <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?actionBarSize"
    android:background="?colorPrimary"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <TextView
        android:id="@+id/toolbarTitle"
        style="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
        android:background="?attr/selectableItemBackground"
        android:layout_width="wrap_content"
        android:gravity="center_vertical"
        android:layout_height="match_parent" />
</android.support.v7.widget.Toolbar>

Then you can set the listener in Activity using this code:

setSupportActionBar((Toolbar) findViewById(R.id.toolbar));

TextView toolbarTitle= (TextView) findViewById(R.id.toolbarTitle);
toolbarTitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // DO SOMETHING HERE
        }
    });


回答6:

If you know the actual text that is in your Title, and you are reasonably sure that no other TextView on the screen shares that title, you can use a recursive View tree search to find it.

This is a great solution because it doesn't require reflection of internal knowledge of how to Toolbar is constructed, and gives you direct access to the TextView.

@Nullable
public static TextView findTextViewWithText(@Nullable View toCheck, String toFind) {

    if (toCheck instanceof TextView) {
        String foundText = ((TextView) toCheck).getText().toString();
        if (foundText.equals(toFind)) {
            return (TextView) toCheck;
        }

    } else if (toCheck instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) toCheck).getChildCount(); i++) {
            TextView found = findTextViewWithText(((ViewGroup) toCheck).getChildAt(i), toFind);
            if (found != null) {
                return found;
            }
        }
    }
    return null;
}

The most reliable view to call this on is the decor view but feel free to experiment what works best for your purposes, your mileage may vary.

View found = findTextViewWithText(
    getActivity().getWindow().getDecorView(), "My Title");
if (found != null) {
  // Do something, like set a click listener
}


回答7:

You can do this easily using Toolbar. Define toolbar in layout xml file as given below:

    <android.support.v7.widget.Toolbar
    android:id="@+id/MainActivityToolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorPrimary"
    app:layout_scrollFlags="scroll|enterAlways"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/app_name"
            android:textSize="30sp"
            tools:ignore="RelativeOverlap"

            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            />
        <Button
            android:id="@+id/LogOutButton"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"

            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"

            android:text="@string/logout" />
    </RelativeLayout>

</android.support.v7.widget.Toolbar>

Then you can set the listener in Activity using this code:

setSupportActionBar((Toolbar) findViewById(R.id.MainActivityToolbar));

logOutButton =  findViewById(R.id.LogOutButton);
logOutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
   //define your function for logout or something else 
   LogOut();
 }
});


回答8:

If you want to use the currently existing ActionBar and not the Toolbar, use the following:

ActionBar actBar = getSupportActionBar();
if(actBar != null) {
    actBar.setTitle(R.string.your_ab_title);
 }

//Set actions to take when the AB is clicked
Toolbar ab = findViewById(R.id.action_bar);
if(ab != null){
    for (int i= 0; i < ab.getChildCount(); i++){

        View child = ab.getChildAt(i);

        if(child instanceof TextView || child instanceof ImageView) {
            child.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String url = "http://www.HoverDroids.com";

                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setData(Uri.parse(url));
                    startActivity(i);
                }
            });
        }
     }
}