A sprite on my android game is set to fall by 5 pixels every 100 milliseconds, this works fine the only problem is that the ImageView itself is only 53dp high, if I make it any bigger the image inside scales with it. Since the ImageView is only 53dp high the image disappears after 1100 milliseconds as it scrolls outside the boundaries of the imageview.
I need the layout height of the ImageView to fill_parent but I need the image to stay the same size instead of scaling with it, here's my current code:
<ImageView
android:id="#+id/blueman"
android:layout_width="0dip"
android:layout_height="53dp"
android:paddingRight="300dp"
android:layout_weight="0.03"
android:src="#drawable/fall" />
Thanks in advance :)
since you didn't give the full code of the layout, I'll make some assumptions...
you're talking about setting your sprite's height to the screen's height without scaling?
There should be a difference between your screen size (that is the root layout item) and the sprites in it. I guess you declared your layout as...:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?gameBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btTap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:layout_marginTop="350dp"
android:background="#drawable/tap"
android:visibility="visible" />
<Button
android:id="#+id/btCellR1C1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="490dp"
android:layout_marginTop="155dp"
android:background="#drawable/cell_red" />
The only thing I had to cope with, was the scaling of my sprites depending on the device's resolution with such a method:
public static void scaleView(View view, int top, int left, int width,
int height) {
top = Math.round(top * scaleY);
left = Math.round(left * scaleX);
width = Math.round(width * scaleX);
height = Math.round(height * scaleY);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
params.topMargin = top;
params.leftMargin = left;
view.setLayoutParams(params);
view.setSoundEffectsEnabled(false);
}
Please give us more details to help you
Best regards
Serge
Related
I have a png image something like below and I need to fill its background color according to its capacity.
For example if tank has oil %100 percent of its capacity, background should be yellow , if has %25 , background should be %25 percent yellow and %75 transparent.
Assume that this is a healthbar in a game.
this is what i have in my layout, just a simple imageview in a linearlayout.
Is there any way to achieve this using animation, clip or something ?
<ImageView
android:id="#+id/ivOilTank"
android:layout_width="0dp"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
android:layout_weight="1">
Change your layout xml to contain-
<FrameLayout
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="#android:color/black"
>
<View
android:id="#+id/percent_highlight"
android:layout_width="0dp"
android:layout_height="match_parent"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/oilTank"
/>
</FrameLayout>
Now wherever you want to highlight the certain percentage of the image -
View highlight = findViewById(R.id.percent_highlight);
highlight.setBackgroundResource(<Color_id>);//Any color you want to set
ViewGroup.LayoutParams layoutParams = highlight.getLayoutParams();
layoutParams.width = (int) (dpToPixel(150) * 25 / 100.0f);//If you want to set 25%
highlight.setLayoutParams(layoutParams);
where dpToPixel() converts dp to pixels -
public int dpToPixel(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Here is my solution,
Since I am not interested in using dp for width property, i looked for another solution. If you want to use dp directly check Shadab Ansari's answer which gave me a clue.
frameLayout
<FrameLayout
android:id="#+id/flOil"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<View
android:id="#+id/progress_view"
android:background="#fc12d108"
android:layout_width="55dp"
android:layout_height="match_parent"
android:layout_margin="1dp"/>
<ImageView
android:id="#+id/ivOil"
android:layout_width="match_parent"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
>
</ImageView>
</FrameLayout>
Code
ViewTreeObserver vto = ivRate.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
public boolean onPreDraw() {
ivRate.getViewTreeObserver().removeOnPreDrawListener(this);
widthTank = ivRate.getMeasuredWidth();//get the width of the imageView which has oilTank image as dp.
ViewGroup.LayoutParams layoutParams = prgrs.getLayoutParams();
layoutParams.width = (int) (widthTank / (new Random().nextInt(4) + 2));//calculate a width for view which is going to fill background color, random was user for testwill be using desired value.
prgrs.setLayoutParams(layoutParams);
return true;
}
});
Before using widthTank variable , onPreDraw method has to be called so be sure that it is called otherwise it will not be assigned.
Please checkout this example
https://github.com/fanrunqi/WaveProgressView or https://github.com/rathodchintan/Percentage-wise-Image-Filling
this is the best way to fill image
Hi guys I am trying to build a layout but I am not able to understand how to build it
what I am trying to do is to add a Image whose height and width will be of screen size and below it will be a description about the Image which the users can view when they scroll it but the whole screen will be consisting of image only until the user scrolls the text below will not be displayed
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/scrollView"
android:fillViewport="true"
>
<RelativeLayout
android:layout_weight="1"
android:id="#+id/relativla"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:background="#drawable/hamburger"
android:id="#+id/navi"
android:padding="10dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:background="#drawable/dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/descrpitiondietplan"
android:id="#+id/textView5"
android:layout_below="#+id/imageView"
/>
</RelativeLayout>
</ScrollView>
you can see in the below link the way i want the layout to be
http://postimg.org/image/avgmk6pi3/
please feel free to drop in comments if you need any additional details
EDIT 1
After trying rachel solution I am getting this
http://postimg.org/image/tdb02gu9l/
now as you can see in the image the image view is taking whole width of the screen which is fine but it doesn't take the whole height of the screen if i write match_parent to the imageview layout_height the image takes the whole screen but it doesn't allow me to scroll
It sounds like you'll need to do some work to get the screen size of the device, then set the image view's size programatically using that.
See the accepted answer here for more details on calculating the device screen size: Android Layout, view height is equal to screen size
Finally got it working after a bit of research on google and stackoverflow finally got a way
so here it is first your activity / fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.second_frag, container, false);
img = (ImageView) v.findViewById(R.id.imageView);
Drawable drawable = getResources().getDrawable(R.drawable.dp);
Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
float scalingFactor = this.getBitmapScalingFactor(bitmap);
Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor);
// Set the bitmap as the ImageView source
this.img.setImageBitmap(newBitmap);
return v;
}
private float getBitmapScalingFactor(Bitmap bm) {
// Get display width from device
int displayWidth = getActivity().getWindowManager().getDefaultDisplay().getWidth();
// Get margin to use it for calculating to max width of the ImageView
RelativeLayout.LayoutParams layoutParams =
(RelativeLayout.LayoutParams)this.img.getLayoutParams();
int leftMargin = layoutParams.leftMargin;
int rightMargin = layoutParams.rightMargin;
// Calculate the max width of the imageView
int imageViewWidth = displayWidth - (leftMargin + rightMargin);
// Calculate scaling factor and return it
return ( (float) imageViewWidth / (float) bm.getWidth() );
}
as i am using fragment I have onCreateView onCreate will be for people using activity
and create a Utils class
public class Util {
public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
int scaleHeight = (int) (bm.getHeight() * scalingFactor);
int scaleWidth = (int) (bm.getWidth() * scalingFactor);
return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
}
if you guys have a better solution do let me know
I am using GridLayout(support) for displaying ImageViews in my application. There are 3 columns and 5 rows. The problem is that the cells in the GridLayout automatically get some space between them. I am not setting any padding or margin for the cells. Please refer to the image below. All cells are added dynamically and here is how I add these cells.
Getting Screen Width and Height:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;
rowHeight = (int) (screenHeight * 0.2);
Adding View to GridLayout:
GridLayout.LayoutParams params = new GridLayout.LayoutParams(
getSpec(rowColumn[0]), getSpec(rowColumn[1]));
params.height = rowHeight;
if (rowColumn[1].equalsIgnoreCase("col_full")) {
params.width = (int) (screenWidth);
} else if (rowColumn[1].equalsIgnoreCase("col_two_part")) {
params.width = (int) (screenWidth * 0.6);
} else {
params.width = (int) (screenWidth * 0.3);
}
ImageButton image = (ImageButton) imageHashMap
.get(reOrderedButtonsListCopy.get(i));
image.setLayoutParams(params);
gridLayout.addView(image, params);
XML Layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/gridlayout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
app:columnCount="3"
app:rowCount="5" >
</android.support.v7.widget.GridLayout>
</LinearLayout>
</ScrollView>
Current result:
The red lines show the spaces in between the cells. Also, there is some space on the left side of GridLayout. I have only given 2dp as layout_margin. Any reasons why this padding occurs?
[EDIT]
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
Found the solution.
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
The only solution that worked for me was to add extra columns in the GridLayout like android:columnCount="7" and then the column that needs more width set to 3 or more. The more space you want to give to that column. It then automatically reserves more space for those columns. The whole GridLayout works as a stretching thing. The columnWeight says how much a column can stretch.
Currently, I have a layout which looks like this. It contains.
Title text view, and Price text view, which is visible always.
Description Text View, which can be visible or gone, depending expanding or collapsing.
Collapsing (During app startup)
Expanding (When user taps on it)
I want to have some nice animation around it. So, I referred to https://stackoverflow.com/a/13381228/72437
One of the key element, is to know the exact height of Description Text View, even before it is visible.
However, I realize a few type of code. They are't accurate
// v is description text view.
v.measure(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
final int targtetHeight = v.getMeasuredHeight();
// v is description text view.
v.measure(MeasureSpec.makeMeasureSpec(LayoutParams.MATCH_PARENT, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
final int targtetHeight = v.getMeasuredHeight();
This will return value 32. (The correct measured height suppose to be 92). This is the height for first line of text. This ends up my animation is ended at
May I know, what is the correct way to determine the measured height of a view, even before it changed from GONE to VISIBLE?
My layout code is as followed :
<LinearLayout
android:clickable="true"
android:id="#+id/chart_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#drawable/dummy"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="0.6"
android:layout_height="match_parent"
android:gravity="left"
android:textSize="20sp"
android:textColor="#ff000000"
android:text="Summary chart" />
<TextView
android:id="#+id/chart_price_text_view"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="0.4"
android:layout_height="match_parent"
android:gravity="right"
android:textSize="20sp"
android:textColor="#ffF76D3C"
android:text="$2.99" />
</LinearLayout>
<TextView
android:visibility="gone"
android:id="#+id/chart_description_text_view"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/currency_exchange_description"
android:textColor="#ff626262"
android:textSize="15sp" />
</LinearLayout>
Your 2nd code snippet is almost correct, but you need to specify pixel sizes - not FILL_PARENT/MATCH_PARENT. This should work:
v.measure(MeasureSpec.makeMeasureSpec(parentView.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(MAX_HEIGHT, MeasureSpec.AT_MOST));
final int targetHeight = v.getMeasuredHeight();
You'll need to have a reference to the ViewGroup that v is a child of to get its width, and define MAX_HEIGHT (or perhaps use the parent View's height?).
Also, you should change the height parameters of the two TextViews that are within the horizontal LinearLayout to wrap_content, as using match_parent here may cause problems. The LinearLayout is set to wrap_content, but the two children don't specify a height.
I accomplished this for my accordion component. I was facing the exact same issue, of expanding my accordion which required the 'destination' height, that is, the height that it would take after the expansion.
This returns the correct height:
/***
* This function returns the actual height the layout. The getHeight() function returns the current height which might be zero if
* the layout's visibility is GONE
* #param layout
* #return
*/
public static int getFullHeight(ViewGroup layout) {
int specWidth = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED);
int specHeight = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED);
layout.measure(specWidth,specHeight);
int totalHeight = 0;//layout.getMeasuredHeight();
int initialVisibility = layout.getVisibility();
layout.setVisibility(View.VISIBLE);
int numberOfChildren = layout.getChildCount();
for(int i = 0;i<numberOfChildren;i++) {
View child = layout.getChildAt(i);
if(child instanceof ViewGroup) {
totalHeight+=getFullHeight((ViewGroup)child);
}else {
int desiredWidth = View.MeasureSpec.makeMeasureSpec(layout.getWidth(),
View.MeasureSpec.AT_MOST);
child.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight+=child.getMeasuredHeight();
}
}
layout.setVisibility(initialVisibility);
return totalHeight;
}
You can take a look at the accordion component and the animation on GitHub: Android Accordion View
This is my very first post at Stackoverflow. Before I make my question, I just want to say that this is a great resource of information and I find the community extremely helpful.
I hope to be able to share my Android development knowledge with everyone else as well.
I have been developing for Android for 6 months now and, although I have learned very much, I still greatly struggle when it comes to layout/design.
I have one layout.xml file that contains a Relative layout. Inside this layout, I have three buttons. I want those three buttons to have a certain width size that would grow or shrink depending on the device's screen size/density.
This is the xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1123123213"
android:layout_width="fill_parent"
android:layout_height="#dimen/actionbar_height"
android:orientation="horizontal">
<Button
android:id="#+id/btnLogin"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="Earned" />
<Button
android:id="#+id/btnLogin2"
android:layout_width="113dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/btnLogin"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="In Progress" />
<Button
android:id="#+id/btnLogin3"
android:layout_width="107dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/btnLogin2"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="Done" />
</RelativeLayout>
I hard coded the width values, considering that I have different text sizes in each button... so that should obviously affect the width as well...
My question is... is there any intelligent way to accomplish this? Maybe programatically, when I know the current device's screen size?
Thanks everyone!
Felipe
====================================================
UPDATED SECTION
Hey guys,
Thanks for your help so far.
I have added the LinearLayout and the weight as per recommendation, but I am still not exactly getting what I want. It's almost there, but not quite.
My new xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="#dimen/actionbar_height"
android:orientation="horizontal"
android:gravity="center" android:weightSum="1">
<Button
android:id="#+id/btnLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="#string/bottonbar_earned"
android:layout_weight=".10"/>
<Button
android:id="#+id/btnLogin2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".10"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="#string/bottonbar_inprogress" />
<Button
android:id="#+id/btnLogin3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center" android:text="#string/bottonbar_redeemed"
android:layout_weight=".90"/>
</LinearLayout>
This is the result link
Can you see the end of the right side? I don't think the weight is distributed like it should, although I set a .90 weight to the third button.
What do you guys think?
What you can do is use android:layout_weight attribute on buttons, but you need to place them into a LinearLayout. If you need to have RelativeLayout, then you can place the LinearLayout inside it.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0" >
<Button
android:text="left"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".30" />
<Button
android:text="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".40" />
<Button
android:text="right"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".30" />
</LinearLayout>
If you could do it in xml itself, I wouldn't recommend doing it programmatically. You can add something like :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center" style="android:style/ButtonBar" >
<Button android:text="Ok" android:id="#+id/bookOkBtn"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:text="Return" android:id="#+id/bookReturnBtn"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
Making android:layout_width="0" & android:layout_weight=1 uses all the available space width wise.
If you want height-wise also, then specify dip in android:layout_height="100dip" and check your desired height.
If this also doesn't fit your needs and dynamic setting is only the solution, then have added Answer for that too.
UPDATED :
Have a look at this code :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:orientation="horizontal" android:gravity="center"
android:layout_marginTop="15dp" style="android:style/ButtonBar">
<Button android:id="#+id/browseAddBtn" android:text="Add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseViewBtn" android:text="Edit" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseDelBtn" android:text="Delete" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseReturnBtn" android:text="Return" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" />
</LinearLayout>
RESULTS
Image shows results of above code and also on changing the layout_weight as mentioned in file respectively. My parent layout is also LinearLayout & has no padding or margins set.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">
This sounds more like a case for a LinearLayout than a RelativeLayout. If you specify a LinearLayout as the parent with a total layout weight of 3 and have each of your Buttons specify a layout weight of 1 they should end up precisely as you desire on any screen.
I had same situation where I had to set sizes of buttons based on screen sizes and density. I calculate the size of buttons based on the actual space for the application I get.
I would suggest you to use LinearLAyout instead of RelativeLayout, but as you have some experience, you must be aware of the differences and ease of usage with Linear rather than Relative layouts.
In my XML I have root LinearLayout & 2 inner LinearLayout (row1 & row2). Each row has 3 butttons.
In my onCreate I get above 3 of them using findViewById.
Using the LayoutParams and the screen's size and densty, I calcualte the size of buttons and text sizes.
Algorithm :
Get Screen height & Width
Deduct the padding & margins you use
Deduct height of Title bar
Now, you have got your full available space. Divide it horizontally & vertically as you need
This will give you size of 1 button
Set the same size to all buttons
Based on buttons width & height & density figure out the text size
You can start up with this, if you need help I will be there. Feel free to ask.
UPDATED : CODE ADDED :-
These methods are added in a class named "Utility" and made static to access the methods in whole project easily :
public static ScreenInfo scrnInfo = new ScreenInfo();
public static void calculateChildSize(LinearLayout root, LinearLayout.LayoutParams row1Params, LinearLayout.LayoutParams row2Params, DisplayMetrics metrics) {
int height, width;
int childWidth, childHeight;
//gets screen dimensions
height = metrics.heightPixels; //480
width = metrics.widthPixels; //320
scrnInfo.setScreenHeight(height);
scrnInfo.setScreenWidth(width);
//Log.i("MY", "Actual Screen Height = " + height + " Width = " + width);
// Get height/width after deducting Padding of all 4 sides
height = height - (root.getPaddingBottom() + root.getPaddingTop()); // 480-70
width = width - (root.getPaddingLeft() + root.getPaddingRight()); // 320-70
//Log.i(TAG, "Actual Area after Padding W = " + width + " H = " + height);
int bottomMargin = row1Params.bottomMargin; //15
bottomMargin = (row1Params.bottomMargin %2) == 0 ? row1Params.bottomMargin : row1Params.bottomMargin+1;
// Actual Height/Width of child
childWidth = (int)(width);
childHeight = (int)(height /2) - (bottomMargin/2);
childHeight -= scrnInfo.getTitleBarHeight();
scrnInfo.setRowHeight(childHeight);
row1Params.height = childHeight;
row1Params.width = childWidth;
row1Params.bottomMargin = (bottomMargin/2);
row2Params.height = childHeight;
row2Params.width = childWidth;
row2Params.topMargin = (bottomMargin/2);
scrnInfo.setChild1LayoutParams(row1Params);
scrnInfo.setChild2LayoutParams(row2Params);
calcTileWidthHeight(childWidth);
calcTileTextSize();
//android.util.Log.i(TAG, "Child W = " + childWidth + " H = " + childHeight + " Tile W = " + scrnInfo.getTileWidth() + " Tile Text Size = " + getTileTextSize());
return;
}
public static void calcTileWidthHeight(int childWidth) {
int margin = 8;
scrnInfo.setTileWidth(((childWidth/3)-margin));
}
public static void findTitleBarHeight(Window win) {
Rect rect = new Rect();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleHeight = contentViewTop - statusHeight;
scrnInfo.setTitleBarHeight(titleHeight); // SET TitleBarHeight
//Log.i(Utility.TAG, "titleHeight = " + titleHeight + " statusHeight = " + statusHeight + " contentViewTop = " + contentViewTop);
return;
}
public static void calcTileTextSize() {
// current is 11 on W = 75 => its small
int w = scrnInfo.getTileWidth();
float ts = 11f;
if (w >= 51 && w <= 70) // Port LDPI W - 54 H -98
ts = 15f;
// Screen 320 * 480 Medium dense
else if (w >= 71 && w <= 80) // Port MDPI
ts = 13f;
else if (w >= 81 && w <= 110) // Land LDPI W - 81 H - 58
ts = 15f;
else if (w >= 111 && w <= 220) // Landscape - Perfect
ts = 18f;
else if (w >= 221 && w <= 250)
ts = 20f;
setTileTextSize(ts);
}
ScreenInfo class contains setters/getters for following members :
public class ScreenInfo {
private int titleBarHeight, screenHeight, screenWidth;
private int rowHeight;
private LinearLayout.LayoutParams child1LayoutParams, child2LayoutParams;
private int _6tiles_Width; // Width of a Tile where 3 tiles on 2rows r shown
NOW comes actual implementation in Activity :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.datapage);
root = (LinearLayout) findViewById(R.id.dataroot);
row1 = (LinearLayout) findViewById(R.layout.datarow1);
row2 = (LinearLayout) findViewById(R.layout.datarow2);
btn1 = (Button) findViewById(R.id.relationBtn);
btn2 = (Button) findViewById(R.id.productBtn);
btn3 = (Button) findViewById(R.id.bankBtn);
btn4 = (Button) findViewById(R.id.locationBtn);
btn5 = (Button) findViewById(R.id.curencyBtn);
btn6 = (Button) findViewById(R.id.dataReturnBtn);
root.post(new Runnable() {
public void run() {
Utility.findTitleBarHeight(getWindow());
// CALCULATE THE SIZE OF INNER LAYOUTS
//calculateChildSize();
LinearLayout.LayoutParams row1Params = (android.widget.LinearLayout.LayoutParams) row1.getLayoutParams();
LinearLayout.LayoutParams row2Params = (android.widget.LinearLayout.LayoutParams) row2.getLayoutParams();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Utility.calculateChildSize(root, row1Params, row2Params, metrics);
row1.setLayoutParams(Utility.scrnInfo.getChild1LayoutParams());
row2.setLayoutParams(Utility.scrnInfo.getChild2LayoutParams());
RefreshComponents();
}
});
}
protected void RefreshComponents() {
// Set background of the root
root.setBackgroundColor(Utility.getBackgroundColor());
// set Gradient Colors & text color of all buttons
RefreshGradientButtons();
}
protected void RefreshGradientButtons() {
GradientDrawable btnGradient = Utility.getButtonDrawable();
int i = -1;
for(i=0; i < row1.getChildCount(); i++) {
Button btn = (Button)row1.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
for(i=0; i < row2.getChildCount(); i++) {
Button btn = (Button)row2.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
}
Whenever screen is changed from Portrait to Landscape or vice-versa OR if at all density is changed at runtime, onCeate is called every such time. Hence this code is added in onCreate(), so the calculations and settings can be appropriately on spot.
In my app, this works like a charm in versions from 1.5 to 3.2 and all density's.
You will have to make changes for your requirement accordingly. As your design is just 3 buttons in a row, while my design for the above code is like Tiles on screen. 2 rows n 3 buttons in each row. I have kept the logs I had added as it will help you to debug and figure out your solution.
This will work 100%.
*I would still recommend to give a try to : just create a new xml and in LinearLayout as parent, add your LinearLayout of buttons and see. Does that work ? While executing try it in both the modes. In your LinearLayout try removing weightSum. According to me, this requirement should be achieved in xml itself. *
BEST LUCK.