ActionBarSherlock (ABS): how to customize the text

2019-03-25 04:56发布

问题:

I'm using ABS vers. 4 and I need to simply change the default "Done" text that is displayed besides the action mode close icon, but I really can't figure out how to do it.

I think that text needs to be customizable for at least two good reasons:

  • "Done" is not appropriate for all contexts (e.g. "Cancel" could be more appropriate, and I've seen some apps, such as the "My Files" app on Galaxy Tab, use it)

  • "Done" needs to be localized according to the user's language

Is it possible to do customize that text? If so can anyone tell me how to do it?

Thanks in advance.

EDIT

I've found a temporary workaround, that I post in the following:

private TextView getActionModeCloseTextView() {
    // ABS 4.0 defines action mode close button text only for "large" layouts
    if ((getResources().getConfiguration().screenLayout & 
        Configuration.SCREENLAYOUT_SIZE_MASK) == 
        Configuration.SCREENLAYOUT_SIZE_LARGE) 
    {
        // retrieves the LinearLayout containing the action mode close button text
        LinearLayout action_mode_close_button =
            (LinearLayout) getActivity().findViewById(R.id.abs__action_mode_close_button);
        // if found, returns its last child 
        // (in ABS 4.0 there is no other way to refer to it, 
        // since it doesn't have an id nor a tag)
        if (action_mode_close_button != null) return (TextView)
            action_mode_close_button.getChildAt(action_mode_close_button.getChildCount() - 1);
    }
    return null;
}

That's the method I came up with. Please NOTE that it does heavily rely upon the structure of the abs__action_mode_close_item.xml of ABS 4.0.

This works for my scenario, but, as you can see, it cannot be considered sufficiently satisfying to promote it to a real "answer", that's why I only edited my previous post.

Hope that helps someone else, but I also hope that someone could share a better and cleaner solution.

回答1:

You can use a theme to override the default icon:

    <item name="actionModeCloseDrawable">@drawable/navigation_back</item>
    <item name="android:actionModeCloseDrawable">@drawable/navigation_back</item>


回答2:

I edited the code from PacificSky to be able to customize the color and font size of the close button, both in pre ICS and >ICS.

I created a method named customizeActionModeCloseButton

private void customizeActionModeCloseButton() {
      int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");    
      View v = getGSActivity().findViewById(buttonId);
      if (v == null) {
         buttonId = R.id.abs__action_mode_close_button;
         v = getGSActivity().findViewById(buttonId);
      }
      if (v == null)
         return;
      LinearLayout ll = (LinearLayout) v;
      if (ll.getChildCount() > 1 && ll.getChildAt(1) != null) {
         TextView tv = (TextView) ll.getChildAt(1);
         tv.setText(R.string.close_action_mode);
         tv.setTextColor(getResources().getColor(R.color.white));
         tv.setTextSize(18);
      }
   }

and I call it just after calling startActionMode()

public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
   actionMode = getActivity().startActionMode(this);
   customizeActionModeCloseButton();
   return true;
}


回答3:

It's been a while, but here's a slightly less hacky solution - putting it out there for posterity.

For Android versions < ICS

Put the following line in your application's strings.xml:

<string name="abs__action_mode_done">Cancel</string>

This overrides the TextView's (defined in ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml) android:text attribute.

For Android versions ICS and above

The native ActionBar functionality is used on ICS and up. You need to find and override the string associated with the done button, using the following code:

int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
if (buttonId != 0)
{
    View v = findViewById(buttonId);
    if (v != null)
    {
        LinearLayout ll = (LinearLayout)v;
        View child = ll.getChildAt(1);
        if (child != null)
        {
            TextView tv = (TextView)child;
            tv.setText(R.string.cancel);
        }
    }
}


回答4:

Thanks for PacificSky's answer. It's useful for my case.

Something needs to be explained here is that findViewById(buttonId) might return null in some cases such as called in onCreateActionMode() function, because the LinearLayout for ActionMode close button not yet initialized at that time I guess.

I want to hide the action mode close button, so i just sendEmptyMessageDelayed in onCreateActionMode() and call PacificSky's 200ms later. It works for me.



回答5:

Here is my approach with Java code:

private void customizeActionModeCloseButton(String title, int iconID) {
          int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");    
          View v = findViewById(buttonId);
          if (v == null) {
             buttonId = R.id.abs__action_mode_close_button;
             v = findViewById(buttonId);
          }
          if (v == null)
             return;
          LinearLayout ll = (LinearLayout) v;
          if (ll.getChildCount() > 1 && ll.getChildAt(1) != null) {
             //custom icon
             ImageView img = (ImageView) ll.getChildAt(0);
             img.setImageResource(iconID);
             //custom text
             TextView tv = (TextView) ll.getChildAt(1);
             tv.setText(title);
             tv.setTextColor(Color.WHITE);
          }
       }


回答6:

com.actionbarsherlock.view.ActionMode contains method:

setTitle

It is used to change text near Close Icon in the ActionBar. ActionMode is available in your com.actionbarsherlock.view.ActionMode.Callback interface implementation methods, like onCreateActionMode.

What you can do - is save incoming ActionMode reference and use it later to change title as your like. Or, if it is not dynamic - you can setup at with your constant in onCreateActionMode.