ActionBar setBackgroundDrawable() nulling backgrou

2020-02-10 04:37发布

问题:

I'm trying to change the background of the ActionBar from a Handler. The end goal is to pass the Handler to an AsyncTask, but for now even calling Handler.sendMessage() from a Thread results in strange behavior. Through the debugger I'm able to see that the Handler receives the Message and subsequently runs setActionBarBackground() through to the end.

The default ActionBar with blue bottom stroke fully disappears from the screen and is not replaced by the new GradientDrawable. I suspect that the background is being somehow nullified. Furthermore, when I focus on the EditText again, the correct GradientDrawable ActionBar background appears. The behavior I would expect is for the background to simple change on actionDone.

Any insight as to why this is happening would be greatly appreciated!

Relevant code:

TestActivity.java

public class TestActivity extends RoboSherlockFragmentActivity {

    @InjectView(R.id.ET_test) EditText testET;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(MainApp.TAG, "onCreate");
        setContentView(R.layout.test_activity);

        testET.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
                if (i == EditorInfo.IME_ACTION_DONE) {
                    String loc = testET.getText().toString();
                    InputMethodManager mgr = (InputMethodManager) getSystemService(
                            Context.INPUT_METHOD_SERVICE);
                    mgr.hideSoftInputFromWindow(testET.getWindowToken(), 0);
                    Toast.makeText(TestActivity.this, "EditText done!", Toast.LENGTH_SHORT).show();

                    /*TestQuery tq = new TestQuery(TestActivity.this, mHandler);
                    tq.execute();*/
                    new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            mHandler.sendMessage(new Message());
                        }
                    }).start();
                }
                return true;
            }
        });
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //setActivityColors();
            setActionBarBackground();
        }
    };

    private void setActionBarBackground() {
        ActionBar ab = getSupportActionBar();
        //Drawable d = WidgetUtils.getActionBarDrawable(TestActivity.this, 0xFF00FFFF);

        GradientDrawable gd = new GradientDrawable(
                GradientDrawable.Orientation.TOP_BOTTOM,
                new int[]{0xFFFFFFFF, 0xFF000000});
        gd.setCornerRadius(0f);
        ab.setBackgroundDrawable(gd);
    }

}

test_activity.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="button"/>
    <EditText
        android:id="@+id/ET_test"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:singleLine="true"
        android:maxLines="1"
        android:lines="1"
        android:inputType="number"
        android:imeOptions="actionDone"
        android:nextFocusUp="@id/ET_test"
        android:nextFocusLeft="@id/ET_test"/>
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="button2"/>

</LinearLayout>

回答1:

Hendrik's workaround does the trick, but not when using a custom title view. This works instead:

actionBar.setBackgroundDrawable(newBackground);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);

You may need a title set for this to work though.



回答2:

I have encountered the same problem. When I dynamically change the background of the action bar with setBackgroundDrawable() to a new GradientDrawable, the action bar turns all black.

I have discovered that this is connected to the action bar title. I don't use the title and have set it to an empty string. For testing purposes I set it to a test string "Test" instead and the problem with setBackgroundDrawable() immediately disappeared. Looks like a bug in ICS to me.

So instead of hiding and showing the action bar the following workaround works for me:

actionBar.setBackgroundDrawable(newBackground);
actionBar.setTitle(".");
actionBar.setTitle("");


回答3:

Well this seems like a crazy edge case, and it happens with both ActionBarSherlock and the Android implementation of ActionBar. I ended up calling ab.hide() and ab.show() to work around it...:(



回答4:

I am using ActionBarSherlock as well, and I too have wanted to change the background Drawable of the ActionBar via calls to setBackgroundDrawable() at arbitrary times. However, I found that after the background colour is set once, subsequent calls to setBackgroundDrawable() just don't seem to have any effect. I think that this is similar to the problem you encountered.

To get around it, I cheated. I just placed a View in my layout that would appear behind the ActionBar, and made the ActionBar itself transparent. The height of the View is easily set to the correct height by calling getHeight() on the ActionBar.