How do I apply mathematical operations to Android dimensions? - android

How do I avoid this hardcoded math...
<resources>
<dimen name="uno">10dip</dimen>
<dimen name="dos">6dip</dimen>
<dimen name="uno_plus_dos">16dip</dimen>
</resources>
<Button
android:layout_marginTop="#dimen/uno_plus_dos" />
...and covert it to something like this?
<Button
android:layout_marginTop="#dimin/uno + #dimen/dos" />

You don't, sorry. Layout XML files do not support expressions. You either:
Leave it as #dimen/uno_plus_dos, or
Set your margins in Java code, where you can replace a single resource with a bunch of extra lines of code, or
Write your own layout preprocessor that handles expressions like this
UPDATE The data binding library supports some operations in its expressions. I am uncertain if it can handle this specific scenario.

One trick for simple addition is to use margin + padding.

Using databinding:
android:layout_marginTop="#{#dimen/uno + #dimen/dos}"
IFAIK margins adapters are not provided by the sdk. You will need to define it yourself:
#BindingAdapter("android:layout_marginTop")
public static void setBottomMargin(View view, int bottomMargin) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin,
layoutParams.rightMargin, bottomMargin);
view.setLayoutParams(layoutParams);
}
Make sure databinding is enabled for your project :
dataBinding {
enabled = true
}
in your build.gradle.
The databinding doc is worth reading.

There's a few tricks around this, but it wouldn't be as nice as your proposed solution, which is something I want as well. For example, you can use layout paddings on not just the View (Button in this case), but you can also do it on the view's parent (the layout like LinearLayout/RelativeLayout). You can also put in invisibile Views (a straight View object works often) with fixed dimensions. It would be like
<View
android:layout_width="1px"
andoird:layout_height="#dimen/dos" />
Note that 1px is fine if want to guarantee only 1 pixel will be drawn for a dimension, which is usually what you want if you want use empty views for padding. Some say FrameLayout is better to use for empty padding, but that's descended from View
Sometimes you can combine padding and the layout padding, but that can get messy and have your view cropped. Also you can have something like a FrameLayout or a LinearLayout contain just that view, and use that to have the added padding

Related

Linear Layout baselinealigned warning on android

i am getting "Set android:baselineAligned="false" on this element for better performance" while using LinearLayout, I know its regarding performance,but i dont know exactly why it is,please clarify me
If you are looking for a visual explanation like me, then you might find this useful.
When baselineAlign is enabled(i.e if it is set to true), then all the text in that line will be aligned to have the same baseline.
Note: By default, baselineAligned is set to true. (i.e. baselineAligned=true)
When you make baselineAligned=false, all it needs to do is to add new elements to the linear layout and be done with it. The app need not worry about where the baseline of other elements in the layout is.
See the image below for more clarity
android:baselineAligned/setBaselineAligned(boolean): When set to false,
prevents the layout from aligning its children's baselines.
So can take example with linear layout with horizontal child views having multiple TextView with different text size or different views like button there basealignment would be different and you cannot adjust it to have same basealignment if you set it to false
Reference
Update:
By setting android:baselineAligned="false" , you're preventing the extra work your app's layout has to do in order to Align its children's baselines; which can obviously increase the performance. (Less unnecessary operations on UI => Better performance) as mentioned here

How to make height more than wrap_content in Android?

I have a ListView where each objects in the list has the parameter:
android:layout_height="wrap_content"
However, this makes the objects hard to press. I don't want to increase the font size to achieve this. Instead, can I add a buffer to wrap_content?
I'd like to implement something like:
android:layout_height="wrap_content" + 10dp
How do I do this?
Thanks
Add some margin or padding to your views. Alternatively, embed a <View> element with fixed 10dip height.
you can use padding property so its automatically set height & width what you want...
android:padding="10dip"
you would have to do that programmatically most likely. Because that method wont work.
Not exact coding but along the lines:
View what_i_want_to_resize = (View)findViewById(R.id.myview);
View view_with_the_size = (View)findViewById(R.id.sizeview);
what_i_want_to_resize.setMinimumHeight(view_with_the_size.getMeasuredHeight() + 10);
Something along those lines. It is impossible to do it with XML.
You can also add padding to it.
android:padding="10dp"
That will make a padding or cushion between the views.
Try using android:layout_margin="10dip" or padding.
You have to give android:layout_height="50dp" or any figure directly

Help with my first Android UI

I'm having trouble developing the UI for my first lame "game".
Here is a screenshot.
I'm using a LinearLayout that contains a TableLayout with TableRows. It seems so tedious and hard to control the position of elements.
For example, to get things to line up, I've inserted empty TextViews to "push" other elements into place.
I've also added padding to the buttons to get them to be the size I want.
Is there a better way of doing this?
Thanks!
You definitely want to be using a Relative Layout for this.
You would be able to specify where each button is in relation to other buttons.
Absolutely AVOID developing your UIs the way you are currently trying. The TextViews will be different sizes for different distributions of Android, and will likely only look right on the device you tested them for.
EDIT:
If you need empty space, use the XML attribute android:weightSum="x" in the parent view and android:layout_weight="y" in the child. This will make the child take up (y/x) of the space allotted to it in the layout_height and layout_width.
EDIT:
I think another good bit of advice for this would be to use individual layouts for things like your "direction" buttons. You'll be able to handle where they are on the screen as a group, instead of having to move each individually.
You should use RelativeLayout to solve this problem. I've gone through a similar problem once...
I didn't use the the Android's default buttons, for I had my own images for the pressed and unpressed behaviors...
Let suppose you want to place the east "button". You could use a function like:
public void addEastImageView(RelativeLayout myBackgroundLayout, ImageView center, ImageView east, int leftPadding, int topPadding, int rightPadding, int bottomPadding){
RelativeLayout.LayoutParams rightSide = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
rightSide.addRule(RelativeLayout.RIGHT_OF, center.getId());
east.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
myBackgroundLayout.addView(east, rightSide);
}
The ImageView called "center" would be the one you called "i" in your image. The padding parameters would allow you to control the distance between the ImageViews. You can create functions like this one to add the "west", "south" and "north" buttons also: you just have to change the parameter "RelativeLayout.RIGHT_OF" to "RelativeLayout.LEFT_OF", "RelativeLayout.BELLOW" and "RelativeLayout.ABOVE" accordingly.
If you want some behavior for your ImageViews, you just have to set it in the setOnClickListener. You can then change your ImageView's "image" with setBackgroundResource, for example, and set the others logic behaviors you want.
Hope it helps :D
Use an AbsoluteLayout - it lets you state exactly where to put every element
http://mobiforge.com/designing/story/understanding-user-interface-android-part-1-layouts
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<Button
android:layout_width="188px"
android:layout_height="wrap_content"
android:text="Button"
android:layout_x="126px"
android:layout_y="361px"
/>
<Button
android:layout_width="113px"
android:layout_height="wrap_content"
android:text="Button"
android:layout_x="12px"
android:layout_y="361px"
/>

Android TextView has height and width of 0

I have a small project where I want to reuse a certain UI component a few time so I created a widget by expanding a ViewGroup. In that ViewGroup I inflated a view that contained a TextView inside a LinearLayout and added that inflated view to the ViewGroup trough addView.
The outer LinearLayout expands itself perfectly but the inner TextView have getHeight() = 0 and getWith() = 0 when I view it through Hierarchy Viewer. The strange thing is that layout_height and layout_width is the values I gave them in my xml.
I don't have the code here but it looked something like this:
xml:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="random text.."
android:layout_with="200px"
android:layout_height="50px" />
</LinearLayout>
Java:
class MyWidget extends ViewGroup {
...
//In constructor
myView = View.inflate(context, R.layout.xml, null);
addView(myView);
//In layout
myView.layout(l, t, r, b);
I have tried to give my text view fill_parent values for size but it didn't help.
Remember:getHeight() and getWidth()return 0 if components are not drawn yet.
To find the width And height of a View before it being drawn:
First call measure
view.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED)
Now you can get width using getMeasuredWidth and height using getMeasuredHeight
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
I have posted some more ideas here: How to get width/height of a View
1) Here is some links to use Hierarchy Viewer on your dev phone.
http://developer.android.com/guide/developing/debugging/debugging-ui.html
and the class you'll need:
http://github.com/romainguy/ViewServer
2) You can also reuse layout like a component with the include tag:
<include android:id="#+id/your_id" layout="#layout/layout_name" />
So, I put a bounty on this one, and here is what I've found.
Inflating with a null reference is A Bad Idea(TM). Essentially, that View won't get the proper layout parameters it needs (its parent sets a whole bunch of them, with a whole bunch of magic/logic involved). So inflating into null means no parents, and no inherited layout parameters. One can manually set a number of these parameters, but due to the magic involved it might not solve your problem.
The "solution(s)" that I've come up with involve; using include (when you know how many you need) and pulling them into code, or inflating to a parent (when you need true dynamic, N things). And of course, the XML you inflate will have ID collisions, so I go about it by grabbing the last child (e.g. getChildAt(getChildCount()-1) ) of whatever I'm looking for, etc.
Did you try passing yourself as the root:
View.inflate(context, R.layout.xml, this);
Since you will be the parent of this View that complies with the javadoc spec.

Set attributes (margin, gravity, etc...) to an Android view programmatically (without XML)

I need to create a GUI (layout+views) in my .java activity class (I know it's far more flexible and easier to use .xml layout file, but I don't want to use it for now).
I can't find any setGravity() (but a "Gravity" object I can't figure how to use) or any set setMargin() method for the "View" object.
What is the easiest way to do it ?
Thanx.
For setting the margin on component. The following leaves the existing margins as previously set and sets the left margin as zero.
TextView title = ((TextView)findViewById(R.id.default_panel_title))
final ViewGroup.MarginLayoutParams lpt =(MarginLayoutParams)title.getLayoutParams();
lpt.setMargins(0,lpt.topMargin,lpt.rightMargin,lpt.bottomMargin);
title.setLayoutParams(lpt);
You can add gravity to the "layouts" not to the "controls". Try to set gravity to any of your Linear/Relative or Frame layouts using setGravity(); .
Eg:
LinearLayout lll = (LinearLayout) findViewById(R.id.layoutname);
lll.setGravity(Gravity.CENTER);

Categories

Resources