简体   繁体   中英

Android: TextView.setLayoutParams sometimes work, sometimes doesn't

I have an android app that let's the user modify some layout parameters. One of my functions let's the user decide if a TextView will be aligned against the top or the bottom of a picture.

This is the function:

private void setAlign(String align) {

    /* Get Preferences */
    SharedPreferences prefs = getSharedPreferences("prefs", Context.MODE_WORLD_READABLE);
    SharedPreferences.Editor editor = prefs.edit();

    editor.putString("align", align);
    editor.commit();

    Log.d("ALIGN", align);

    paramAlign = align;

    FrameLayout.LayoutParams floLP = new FrameLayout.LayoutParams(
                                            FrameLayout.LayoutParams.WRAP_CONTENT,
                                            FrameLayout.LayoutParams.WRAP_CONTENT,
                                            (align == "TOP") ? Gravity.TOP : Gravity.BOTTOM);

    txtGoal.setLayoutParams(floLP);

    int res = paramAlign == "TOP" ? R.drawable.btn_toolbar_align_top_up : R.drawable.btn_toolbar_align_bottom_up ;
    btnAlign.setImageResource(res);

}

Now once the activity is started, this function works fine. However, when I initialize the activity, I call the setAlign() function in the onGlobalLayout method after retrieving the alignment preference.

This is the relevant code:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.personalize);

    /* Get Preferences */
    SharedPreferences prefs = getSharedPreferences("prefs", Context.MODE_WORLD_READABLE);

    paramAlign = prefs.getString("align", "BOTTOM");

    Log.d("ALIGN", paramAlign);

    // Get screen dimensions and initialize preview
    ViewTreeObserver vto = rootView.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {

        setAlign(paramAlign);

        ViewTreeObserver obs = rootView.getViewTreeObserver();
            obs.removeGlobalOnLayoutListener(this);
        }

    });

}

Now if you notice the logging functions, they both return "TOP" when I start the activity. And the setAlign() function is obviously getting called. Yet, the TextView is aligned at the bottom. This is the XML for the TextView:

<TextView
                android:id="@+id/txtGoal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:textColor="@color/color_white"
                android:textSize="8sp"
                android:shadowColor="@color/color_black"
                android:shadowDx="1.2"
                android:shadowDy="1.2"
                android:shadowRadius="1.2"
                />

Any idea why the setLayoutParams is not happening when the activity is created? The function is getting fired when the layout is done being drawn so it shouldn't be the issue here. And the XML has no gravity specified to start with.

What am I missing here?

First of all, I see that the variable txtGoal is not initialized (nor even declared) so I am assuming you did that somewhere else (that is not posted in the question).

The behavior you are encountering is pretty much normal : the function is working only at start-up, and that's because once you change the layout of your text view, you must indicate that so it will be redrawn, by adding the following :

txtGoal.invalidate ();

after this :

txtGoal.setLayoutParams(floLP);

EDIT:

You can also try changing the gravity in a different way:

 
 
 
  
  txtGoal.setGravity ( Gravity.TOP );
 
  


EDIT:

My apologies, what I suggest (the second solution) is wrong, because it changes the gravity of the text inside the text view (and not the gravity of the text view inside the root view).

Please try the following:

Do not try to modify the gravity of your text view using a listener, you can directly apply the gravity you want after setting the content view of your activity (because the text view is thus created). I advise the following:

Apply the new layout to your text view directly (not via the listener) after retrieving the shared preferences.

Your onCreate method should look something similar to this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.personalize);

    /* Get Preferences */
    SharedPreferences prefs = getSharedPreferences("prefs", Context.MODE_WORLD_READABLE);

    paramAlign = prefs.getString("align", "BOTTOM");

    setAlign(paramAlign);

}

You should compare two string using the equals method:

Replace that :

(align == "TOP")

By that

align.equals ( "TOP" )

And this :

paramAlign == "TOP"

By this :

paramAlign.equals ( "TOP" )

So, here is what I found out and what I did to fix my problem.

Apparently the condition

align == "TOP"

Was not testing true when the activity was started altho the Log dump would tell me that it was in fact true at the time. Now why it did that I have no clue. This seems like a weird bug. That condition tested true once the activity was running.

Since this parameter could only have 2 values, I switched it to a Boolean variable where false is now the equivalent of "BOTTOM" and true the equivalent of "TOP" and it is working perfectly.

This is something that might actually need to be looked into as the condition should of tested true at startup.

** EDIT **

You cannot compare 2 strings in java using the "==" operator. You have to use .equals() instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM