Search code examples
androidlayoutandroid-2.3-gingerbread

Android 2.3.4: How do I determine the dimensions of an image to customize the layout during startup?


I'm trying to customize a relative layout during onCreate() and am having problems because ImageView's getWidth() and getHeight() properties return zero. Several threads here say that this is because the layout hasn't been drawn yet, so it is too early to know the actual image dimensions.

At what point in the lifecycle should I be doing this?

This is what I'm trying to accomplish, without hard-coding the image width:

enter image description here

Here's the app's layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" 
    android:background="#44000000"
    >

    <RelativeLayout 
        android:id="@+id/bannerAdLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="60dip"
        android:orientation="horizontal"
        android:clickable="true"
        android:background="#00000000"
        >

       <LinearLayout android:id="@+id/bannerAdActionButtonLayout" 
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:background="#ff00ff00"
            >
            <!-- NOTE: image's left margin set at run-time -->
            <ImageView android:id="@+id/bannerAdThumbnail"
                android:contentDescription=""
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_launcher"
                />
        </LinearLayout>

        <!-- NOTE: layout's left margin set to 50% of screen width at run-time -->
        <LinearLayout android:id="@+id/bannerAdTextLayout" 
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:background="#ffffffff"
                >
                <TextView android:id="@+id/bannerAdInstructions"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="left"
                    android:text="First line of text"
                    />
                <TextView android:id="@+id/bannerAdTitle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="left"
                    android:text="Second line of text"
                    />
        </LinearLayout>        
    </RelativeLayout>
</RelativeLayout>

And code from onCreate() to customize the layout and set the imageview's left margin so that it is positioned to the left of center:

private Context mThisActivityContext = null;
private Resources mResources = null;

private ImageView mBannerAdImage = null;
private TextView mBannerAdLabel = null;
private TextView mBannerAdOffer = null;
private RelativeLayout mBannerAdLayout = null;
int mBannerAdImageWidth = 48;  // set a default width

// Screen dimensions
private int mScreenHeight;
private int mScreenWidth;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mThisActivityContext = MainActivity.this;
    mResources = mThisActivityContext.getResources();

    setContentView(R.layout.activity_main);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    // get screen dimensions
    mScreenHeight = mThisActivityContext.getResources().getDisplayMetrics().heightPixels;
    mScreenWidth = mThisActivityContext.getResources().getDisplayMetrics().widthPixels;
    Log.w(TAG, String.format("Device screen dimensions are: %d w x %d h", mScreenWidth, mScreenHeight));

        // get the banner ad layout
    mBannerAdLayout = (RelativeLayout)findViewById(R.id.bannerAdLayout);
    // get the image to use for the banner ad
    mBannerAdImage = (ImageView)findViewById(R.id.bannerAdThumbnail);
    GetImageFromAsset(mResources, mBannerAdImage, "ic_launcher");
    Log.w(TAG, String.format("Image ic_launcher dimensions are %d W x %d H", mBannerAdImage.getWidth(), mBannerAdImage.getHeight()));

    // get the banner ad TextView controls
    mBannerAdLabel = ((TextView)findViewById(R.id.bannerAdInstructions)); 
    mBannerAdOffer = ((TextView)findViewById(R.id.bannerAdTitle)); 

    // initialize the banner ad layout
    initBannerAdLayout();
}

    // set an image's bitmap from the specified asset
private void GetImageFromAsset(Resources res, ImageView image, String assetName) {
    try {
        int drawableId = res.getIdentifier(assetName, "drawable", "com.example.animationtest");
        Bitmap bMap = BitmapFactory.decodeResource(res, drawableId);
        image.setImageBitmap(bMap);
            if (image.getWidth() > 0) {
                mBannerAdImageWidth = image.getWidth();
            } 
    }
    catch (Exception e) {
        Log.e(TAG, "Failure to get drawable id for " + assetName, e);
    }
}

// initialize the Banner Ad layout based on the screen dimensions
private void initBannerAdLayout() {
    // reset the background color
    mBannerAdLayout.setBackgroundColor(Color.TRANSPARENT);

    // use margin layout parameters to set the position of the action button within its LinearLayout
    int marginLeft = (int)(mScreenWidth * 0.5) - mBannerAdImageWidth;
    MarginLayoutParams params = (MarginLayoutParams)mBannerAdImage.getLayoutParams(); 
    params.setMargins(marginLeft, 0, 0, 0); 
    mBannerAdImage.setLayoutParams(params);
    Log.w(TAG, String.format("Image left margin is %d, image width is %d", marginLeft, mBannerAdImage.getWidth()));  // xxx

    // use margin layout parameters to set the position of the inner text LinearLayout
    LinearLayout bannerAdTextLayout = (LinearLayout)findViewById(R.id.bannerAdTextLayout);
    marginLeft = (int)(mScreenWidth * 0.5);
    params = (MarginLayoutParams)bannerAdTextLayout.getLayoutParams(); 
    params.setMargins(marginLeft, 0, 0, 0); 
    bannerAdTextLayout.setLayoutParams(params);
    Log.w(TAG, String.format("Text layout left margin is %d", marginLeft));

    mBannerAdLayout.invalidate();
}

Solution

  • Create a bitmap from the drawable resource.

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    

    Once you have the bitmap, you can get the image dimensions through bitmap.getWidth() & bitmap.getHeight().