AppCompat v7 r21 changing Alpha of the ActionBar&#

2020-07-27 05:53发布

问题:

With the previous versions of AppCompat it was easy to get the ActionBar's title TextView and modify it.

There is the method I was using:

 private TextView getActionBarTitleView() {
     int id = getResources().getIdentifier("action_bar_title", "id", "android");
     return (TextView) findViewById(id);
}

And then to change the alpha's value of the title:

getActionBarTitleView().setAlpha(ratio*255);

Now for some reasons, "action_bar_title" with the lastest AppCompat version isn't working anymore. When I tried to use my method, it returned me "null". Tried to use other id's of the ActionBar but I didn't find the good one.

I saw 1 post on StackOverflow from Ahmed Nawara and the only way he found for the moment was to do an Iteration over the Toolbar's children views and whenever a TexView is found, compare it's text value with the toolbar.getTitle() to make sure that's the TexView we're looking at.

If someone could help me to integrate this solution in my case because I don't know how to do it actually.

回答1:

I guess you got your method from Flavien Laurent's post on making the ActionBar not boring. If you take a closer look, he detailled another technique to set the ActionBar title's alpha inspired by Cyril Mottier.

It uses a custom AlphaForegroundColorSpan class that extends ForegroundColorSpan :

public class AlphaForegroundColorSpan extends ForegroundColorSpan
{
    private float mAlpha;

    public AlphaForegroundColorSpan(int color)
    {
        super(color);
    }

    public AlphaForegroundColorSpan(Parcel src)
    {
        super(src);
        mAlpha = src.readFloat();
    }

    public void writeToParcel(Parcel dest, int flags)
    {
        super.writeToParcel(dest, flags);
        dest.writeFloat(mAlpha);
    }

    @Override
    public void updateDrawState(TextPaint ds)
    {
        ds.setColor(getAlphaColor());
    }

    public void setAlpha(float alpha)
    {
        mAlpha = alpha;
    }

    public float getAlpha()
    {
        return mAlpha;
    }

    private int getAlphaColor()
    {
        int foregroundColor = getForegroundColor();
        return Color.argb((int) (mAlpha * 255), Color.red(foregroundColor), Color.green(foregroundColor), Color.blue(foregroundColor));
    }
}

Then, using a SpannableString, you just set the alpha to the AlphaForegroundColorSpan, and then set this AlphaForegroundColorSpan to the SpannableString :

public void onCreate(Bundle savedInstanceState)
{
    ...
    spannableString = new SpannableString("ActionBar title");
    alphaForegroundColorSpan = new AlphaForegroundColorSpan(0xffffffff);
    ...
}

private void setActionBarTitle(int newAlpha)
{
    alphaForegroundColorSpan.setAlpha(newAlpha);
    spannableString.setSpan(alphaForegroundColorSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    getSupportActionBar().setTitle(spannableString);
}

Hope it helps. If it's not clear enough, give another look to Flavient Laurent's post!



回答2:

With AppCompat you should use the new toolbar including the toolbar.xml in the activity layout and importing android.support.v7.widget.Toolbar.

In your activity, OnCreate you will have:

mtoolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mtoolbar);
getActionBarTitleView().setAlpha(ratio*255);

at this point you are almost done and you can use reflection to access to the view (remember to import java.lang.reflect.field;) and your function will be:

 private TextView getActionBarTitleView() {
     TextView yourTextView = null;
        try {
          Field f = mToolBar.getClass().getDeclaredField("mTitleTextView");
          f.setAccessible(true);
          yourTextView = (TextView) f.get(mToolBar);
        } catch (NoSuchFieldException e) {
        } catch (IllegalAccessException e) {
    }
    return yourTextView;
}