I have a fragment named HostFragment which nests one to four other fragments.
This is the layout of HostFragment:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hostFragmentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="12dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<RelativeLayout
android:id="#+id/fragmentContainer1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/fragmentContainer2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<RelativeLayout
android:id="#+id/fragmentContainer3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/fragmentContainer4"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
</TableRow>
</TableLayout>
The important part of this is android:layout_marginTop="12dp".
Background: The nested fragments cover the entirety of HostFragment except for this margin. When the nested fragments change their background color (by calling Canvas#drawColor), HostFragment needs to also change the color of this margin to match. I store the needed color in SharedPreferences.
Behavior: If the user goes from HostFragment to SettingsActivity, changes the color, and comes back to HostFragment, the nested fragments will change their color immediately (through their onResume() methods), but HostFragment's margin will still be the old color. If the user then leaves HostFragment and goes to another fragment, then returns to HostFragment, the margin will update its color. I don't know how or why - I have no code in HostFragment to update the color. The code in HostFragment only deals in swapping in and out nested fragments.
Problem: I need the margin color to update right away, so in onResume(), I've tried something like mTableLayout.setBackgroundColor(...) or even mView.setBackgroundColor(...) (mView is the layout I inflate in onCreateView()). This still doesn't work, and the color will only update if the user leaves and comes back.
Question: How can I change the color of the margin to match an int value in SharedPreferences once the user returns to HostFragment from another Activity (i.e. Right after the user returns from the Settings)?
Thank you in advance!
Try giving paddingTop instead of marginTop and then change the color of the view in onResume by mView.setBackgroundColor(...).
Margin is the space outside the View so background color of a view won't reflect in margin space.
Padding is the space inside of a view and background color given to a View will be applied to padding space as well.
Setting the color of a margin is not possible. To achieve something that looks like that though, there's two things to do.
1) Use padding instead of margin.
Margin is outside of an element, while padding is inside of the element. This means that the element will grow in size, and that the color you've given your element as background-color will also apply to the area around the content.
2) Use a border, or drawable.
This way of doing it requires more work, but is very highly configurable. Creating a border is done by simply setting a drawable as background, and giving it a stroke width and color. For more information (and an example implementation) see https://stackoverflow.com/a/8203840/4330555.
For more information on margin, padding, border etc. see http://www.w3schools.com/css/css_boxmodel.asp. This website explains it for CSS, but the concept is the same pretty much anywhere.
try this,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/c1_cnxlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/black" >
<RelativeLayout
android:id="#+id/c2_cnxlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="#android:color/darker_gray" />
</RelativeLayout>
In order to change the color .setBackgroundColor(...) should work in onResume(), but you should be aware that as it has been pointed out above, a margin area is the space that is left outside from your view within the reference of its parent view. That is why changing a view´s background color would not have effect on the margin. What you could do is add a FrameLayoutthat wraps your TableLayout so that your TableLayout has a reference to set the margin from. In that case, you should be able to change FrameLayout's background and it should affect the desired margin area.
In the image below, the red rectangle represents your TableLayout as you can see on the left, it is the root view of your HostFragmentand the margin area is outside of your reach.On the right, the root view of your HostFragment is a FrameLayout and the red rectangle is still your TableLayout. In the later case, you can change the color of the FrameLayout.
image : http://oi59.tinypic.com/jz8q46.jpg
best way is to use background resource specifying multiple shapes with different color and use margin or padding..
Related
I'm trying to insert a fragment into my application and it's essentially a coloured bar with a few buttons on it. However, whenever I put the fragment onto the main xml file, there's always a bit of a white margin regardless of whatever I do. Here's an sample of some of the fragment code I have in my main xml:
<fragment
android:layout_width="fill_parent"
android:layout_height="50dp"
android:name="sample"
android:id="#+id/sample"
tools:layout="#layout/sample"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_margin="0dp" />
Even though I set the margin to 0dp and the width to fill_parent, there's still a white margin/border on the outside. Is there any way to make a fragment fill the screen widthwise entirely? Thank you!
You have padding and/or margin defined in your parent's ViewGroup that is causing the Fragment's extra spacing. Check the Parent who contains the Fragment and remove the padding :)
I'm implementing a simple flip-clock / counter / ticker widget which will consist of several instances of a following "digit" widget:
It's a digit placed on top of a background image. The digit is supposed to animate every second by sliding up and revealing next digit. During the animation both digits should stay "within" the background's boundary.
I'm trying to achieve this behavior by having a TextView with 2 lines - one digit per line - and animating this TextView's position upwards, until the next digit is fully visible. And then I will reset TextViews position and replace both digits at the same time, so that it's impossible to notice. Then I will repeat the process and make it look like the animation never ends.
Here you can see an intermediate state of the animation, when part of zero and part of nine is visible. I "mocked" it in the Graphical Layout editor of Eclipse, by setting the layout_marginTop property to a negative value.
Here's the layout file (the mentioned attribute is normally not there).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:clipChildren="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<TextView
android:id="#+id/textview_countdown_digit"
style="#style/TextView.CountdownDigit"
android:layout_marginTop="-12dp"
android:text="0\n9" />
</LinearLayout>
</LinearLayout>
I tried two solutions. By using ViewPropertyAnimator on either translateY or y, I get a smooth animation, but the original clipping of the TextView does not change during animation, so in effect the second digit is never visible. As you can see, I tried clipChildren property, but it doesn't seem to change anything.
My second approach was to use ValueAnimator with a custom Evaluator, which modifies the topMargin of LayoutParams on the TextView. It works, but the animation is very choppy even on high-end devices.
So my question is, how to avoid view clipping during animation and make so in an efficient way? Is there a better approach?
I found an alternative solution in which I use a ScrollView instead. My layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollview_countdown_digit"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:scrollbars="none" >
<TextView
android:id="#+id/textview_countdown_digit1"
style="#style/TextView.CountdownDigit"
android:text="0\n9" />
</ScrollView>
I animate using ObjectAnimator by scrollY property. Works well so far.
I also tried having 2 TextViews intsead of one (in my initial layout), but it did not change the fact of clipping.
I need to add to add ListView with complicated items background: different for even/odd and rounded corners at the top and bottom. It looks like this:
I have implemented all this stuff via level-list, but there is one more thing I want to do.
Now the bottom item is near the bottom of the screen. It is better to add some space.
I don't want to add bottom margin to ListView, I need margin only for last item.
The ways I see to do this:
Footer
A kind of hack – add footer with empty TextView to ListView. But footers are quite unstable things, they usually disappear after notifyDataSetChanged and there is no way to get them back
Image with transparent pixels
I asked designer to add transparent pixels to bottom background resource. Unfortunately, in this case vertical centering is completely broken.
For example, there is 9patch like this:
And layout like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- View with background with transparent pixels on bottom -->
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
android:id="#+id/item"
android:background="#drawable/some_bgr"
android:padding="10dp"
>
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"
android:text="Title"
android:layout_gravity="center"
android:textSize="18sp"
/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Detail"
android:layout_gravity="center"
android:textSize="18sp"
/>
</LinearLayout>
<!-- Just for marking place took by view -->
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"
android:layout_below="#id/item"
android:background="#88ff55"
/>
</RelativeLayout>
The result:
As you see, centering is not working. Unfortunately.
(BTW, if specify this 9patch as background for TextView, centering works good. If you know any article, explaining this, please let me know.)
Add bottom margin to last item in Adapter implementation
That should work, but for unknown reason I still can't get it work.
I don't like this way, because I don't like to modify dimensions in code.
So
There is already imaginary way – construct some XML drawable with particular bitmap and margin. According to drawables concept it should be possible, but I can't find implementation. May be somebody knows?
Any other ideas?
In your ListView, set a paddingBottom and clipToPadding="false".
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="8dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"/>
This also works for RecyclerView.
Only use android:scrollbarStyle="outsideOverlay" if you want the scroll bar to not overflow into the padded area.
add an empty footer in your list like this:
TextView empty = new TextView(this);
empty.setHeight(150);
listview.addFooterView(empty);
you can also do it from code if you want, for example here I react to
to EditText different situations:
if(s.toString().length()>0)
{
contacts_lv.setClipToPadding(false);
contacts_lv.setPadding(0,0,0,270*screenDensity);
}
else
{
contacts_lv.setClipToPadding(true);
contacts_lv.setPadding(0,0,0,0);
}
Clocksmith's answer is the best and pretty clever. You can also create an empty footer view.
Add these two lines in your listView XML code:
android:transcriptMode="alwaysScroll"
android:stackFromBottom="true"
Another solution might be that you make a mock view with certain height.
In your adapter in getViewCount return 2.
In getCount return yourData.size+1.
In getViewType check if the element is last element return 2;
Use this type in getView to populate the mockview.
I guess you want to add margin only to last item:
So you can do in this manner, in your getview method the index of the list item and check if its the last item, then progrmatically add margin to the view.
I've got the following xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1"
android:background="#android:color/transparent"
android:layout_marginTop="0px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="1"
android:orientation="horizontal">
<Button android:id="#+id/info" android:text="Info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/town" android:text="Town" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/unit" android:text="Unit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:layout_height="wrap_content" android:text="EndTurn" android:id="#+id/endturn" android:layout_width="wrap_content" android:layout_gravity="bottom"></Button>
</LinearLayout>
which provides the following result: http://i42.tinypic.com/otdkb4.png
Now I've got some questions about this:
The top and bottom padding, how to get rid of it?
I tried RelativeLayout, multiple layouts within each other, padding, margin, changing height nothing seem to affect it in any way.
Is there a way to get the layout transparent? android:background seems to be the wrong one.
Between the third and the fifth button is a bit more space (where the fourth button should be). I catch it the in the program and set it to invisible.
unitButton.setVisibility(INVISIBLE);
unitButton.setWidth(0);
Now the space between the two buttons is more than double of the normal range (between 1 and 2) Any idea on this? - Altough this is a minor problem
Thanks in advance.
1: Is the layout presented in a Dialog? If so, that'll give you some headaches. To get more control you should either create your own custom Dialog extension (as some dialog layout values are hardcoded), or display your layout in another way (a new activity on top, or using a framelayout perhaps)?
2: To get a layout transparent, simply don't give it a background-attribute. (Though, if you really are using a dialog, the dialog box is not transparent, and it is that which you see. You can also set it to be transparent by setting background to "#00000000" (which is what you do).
3: A View with visibility as "invisible" is still measured, that means both its width/height as well as its margins and padding is displayed as empty space in your layout. Setting the visibility to "gone" instead will not measure it, and you won't need the setWidth(0) either. (You can still display it later by setting it back to "visible")
Edit: removing the unused "weightSum" attribute might also be a good idea, as the view is now expecting its children to have a total weight of something other than 0.
I've observed a behavior with layout_weight that I can't explain. The following is a trivial example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="This is a very very very very very very very very very very very very very very very long string."
android:layout_weight="1"
/>
<View
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical"
android:background="#ffffffff"
/>
</LinearLayout>
In a QVGA display, the TextView wraps the text. The white square is displayed to the right of the text.
However, if I remove android:layout_weight="1" from the TextView, the TextView now takes up the entire display width. The white square is no longer displayed.
Why would layout_weight in the TextView affect whether or not the white square is displayed? Shouldn't the View with the white background always be assigned 32dpx32dp first? (It makes no difference if the view were any other types - ImageView or TextView).
The problem I was working on is that I want the white square to always be displayed to the right of the TextView (whether or not the text is wrapped), but I don't want any empty space between the TextView and the white square. (If I add android:layout_weight="1" to the TextView, then there is a gap if the text is not wrapped.)
Any help would be appreciated!
To answer my question #1: One thing I learned by looking at the source for LinearLayout: Not only does layout_weight assign unused space to a child, it also shrinks a child with layout_weight if the child extends beyond the bounds of the LinearLayout. That explains why a TextView with wrapped text is shrunk in my layout.
As for the answer to my question #2, I think you meant android:toRigthOf instead of android:layout_alignRight. Using a RelativeLayout instead of a LinearLayout doesn't change the layout behavior. The tricky part is placing a view immediately to the right of a TextView, without gaps, whether or not the text is wrapped. Setting a maxWidth would limit the TextView's width, but that solution doesn't scale across portrait/landscape and different display dimensions.
Solution - Looks like Dyarish's solution is the best available. My layout problem exists regardless of the layout you use. The key is to set a maxWidth for the TextView so that it doesn't take up the all of the horizontal space in the layout. Because hardcoding a android:maxWidth value in the TextView doesn't scale across different displays, setting the maxWidth at runtime, as Dyarish suggested, is a good solution.
Hopefully this is what you are looking for.
First off, here is a great resource I found for Creating UI's.
layout_weight - Specifies how much of the extra space in the layout to be allocated to the View.
If you want to ensure that the white square is always to the right of the textview, you can use a Relative View, and add the parameter to the view. android:layout_alignRight="+id#yourTextViewID". This should always make the box appear right beside the textView area. You should probably also add something like android:maxWidth="250px" This will ensure that you don't push the white box completely out of the screen.
Here is a code sample:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:maxWidth="250px"
android:id="#+id/TextForWhiteBox"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:text="This is a very very very very very very very very very very very very very very very long string."
/>
<View android:background="#ffffffff" android:layout_width="32dp" android:layout_height="32dp" android:id="#+id/view1" android:layout_toRightOf="#+id/TextForWhiteBox"></View>
</RelativeLayout>
You could also add to the View:
android:layout_alignTop="#+id/TextForWhiteBox" android:layout_alignBottom="#+id/TextForWhiteBox"
to make the white box the same size as the TextView.
Firstly I've tested the code from my other answer and it does exactly what you've described you've wanted. (unless I'm misunderstanding what you are asking for). You definitely do not want to use the android:layout_alignRight which is not what is in the code sample. That would simply keep the box on the right hand of the screen and not be affected by the textview at all. This sample uses android:layout_toRightOf="#+id/TextForWhiteBox" which is possible due to it being a relative layout. Since the Relative Layout allows you to place objects in relation to others. That line will always place the box just to the right of the textview with no gaps.
As for the screen orientation changes:
When the orientation changes it creates a new instance of the view.
Here is a simple solution.
//Add to oncreate in your Activity
private TextView textStatus;
textStatus = (TextView) findViewById(R.id.TextForWhiteBox);
// This get's the width of your display.
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
// Now you know the screen orientation, and it's width. So just set the maxwidth of the text view to match the display width - the pixels of your white box.
textStatus.setMaxWidth(width - 32); // 32 is here because you already know the size of the white box. More logic is needed to dynamically get this value, because you would need to wait for the activity to be fully created.
}
Here is the main.xml I used:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:id="#+id/TextForWhiteBox"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:text="This is a very very very very very very very very very very very very very very very very very very very long string."
/>
<View android:background="#ffffffff" android:layout_width="32px" android:layout_height="32px" android:id="#+id/view1" android:layout_toRightOf="#+id/TextForWhiteBox"></View>
</RelativeLayout>
You might need some additional logic to keep screen values.
This code has been tested, you should be able to literally copy and paste this to work as you asked.
Also depending on your logic you could use something like this to return the screen orientation.
int orient = getResources().getConfiguration().orientation;
Hope this helps!
If this helped you, please click the accepted button. =) Cheers!