I currently have a RelativeLayout within my application which I dynamically move, resize, and hide. After moving it once, the layout is repositioned to a weird location afterwards.
Here is the layout that I am using.
<RelativeLayout ...>
<RelativeLayout android:id="#+id/moveable_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:visibility="gone" />
</RelativeLayout>
And here is the code that I use to relocate it
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(newWidth, newHeight);
m_movingFrame.setEnabled(true);
m_movingFrame.setLayoutParams(layoutParams);
m_movingFrame.setX(newX);
m_movingFrame.setY(newY);
m_movingFrame.requestLayout();
m_movingFrame.bringToFront();
m_movingFrame.setVisibility(View.VISIBLE);
And here is the code used to hide the layout
m_movingFrame.setEnabled(false);
m_movingFrame.setVisibility(View.GONE);
The first time that I relocate it, it moves to the correct position, but every subsequent relocation moves it to the wrong location. Can anyone tell me why it is behaving so erratically?
Thanks in advance!
First get the layout of the existing layout and then modify it.
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) m_movingFrame.getLayoutParams();
...
m_movingFrame.setLayoutParams(layoutParams);
Related
I have 2 views and I'm showing them one below the other one like this(both of them children of the same parent:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/view1"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00FF00"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/view2"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#0000FF"
app:layout_constraintTop_toBottomOf="#id/view1" />
</android.support.constraint.ConstraintLayout>
All works fine but when I change view1 position with setY method the view2 view not updating it's y position too.
I tried to call invalidate and requestLayout, but nothing helps.
How can I refresh or update the constraints after setting the position.
This is a little confusing, so bear with me. setY() does the following:
Sets the visual y position of this view, in pixels. This is equivalent to setting the translationY property to be the difference between the y value passed in and the current top property.
And setTranslationY() does this:
Sets the vertical location of this view relative to its top position. This effectively positions the object post-layout, in addition to wherever the object's layout placed it.
The key phrase here is "positions the object post-layout." In other words, the view that is the subject of setY()is positioned according to the layout then is moved to the new location based upon the argument to setY(). This does not result in another layout. In essence, although the view appears in its new location, it is, effectively, still in its original location. Invalidating and requesting another layout just causes the same layout to occur followed by the translation.
Setting the top margin as Ben P. suggests should work to move the view.
I am not exactly sure why setY() doesn't also update the second view, but you can work around it by setting the first view's top margin instead of calling setY():
ConstraintLayout.LayoutParams params =
(ConstraintLayout.LayoutParams) view1.getLayoutParams();
params.topMargin = 200;
view1.setLayoutParams(params);
Here is my solution:
Just move view1 using setTranslationY(), then assign view1 translationY to view2.
Java example:
view1.setTranslationY(10f);
view2.setTranslationY(view1.getTranslationY())
Kotlin version:
view1.translationY = 10f
view2.translationY = view1.translationY
I am developing an Android app where I have two different views. Both views are actually canvas drawings (drawn programmatically) with a bunch of text views and buttons on top. The positions of these buttons and text views need to be changed depending on the view selection. I created a relative layout with my drawing and the buttons and text views. I use one of the text views as an anchor for the others and programmatically change its position.
Here is a part of the xml:
<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/tvAnchor"
android:layout_above="#id/btnCtrl"
android:layout_marginBottom="130dp"
android:textSize="15sp"
android:textColor="#color/lightGrey"
android:gravity="center"
android:text="#string/Select1"
android:background="#drawable/controls_border_not_active"
android:clickable="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/tvAlign"
android:layout_alignBottom="#id/tvAnchor"
android:layout_toStartOf="#id/tvAnchor"
android:layout_marginEnd="2dp"
android:textSize="15sp"
android:textColor="#color/lightGrey"
android:gravity="center"
android:text="#string/Select2"
android:background="#drawable/controls_border_not_active"
android:clickable="true"/>
In my main I have the following code to change the position of the text views accordingly:
private void PositionControls(){
RelativeLayout.LayoutParams lopAnchor = (RelativeLayout.LayoutParams) tvAnchor.getLayoutParams();
if (isView1Selected){
lopAnchor.resolveLayoutDirection(relativeLayout.getLayoutDirection());
lopAnchor.removeRule(RelativeLayout.ALIGN_START);
lopAnchor.setMargins(0,0,0,370);
lopAnchor.addRule(RelativeLayout.CENTER_HORIZONTAL);
}else{
lopAnchor.setMargins(0,0,0,300);
lopAnchor.removeRule(RelativeLayout.CENTER_HORIZONTAL);
lopAnchor.addRule(RelativeLayout.ALIGN_START,swDoIt.getId());
}
tvAnchor.setLayoutParams(lopAnchor);
}
Basically, in View1, the tvAnchor should be centered horizontally and in the other view it should be positioned off center - in the middle of 'center-to-right screen edge'. In order to do that when the second view is selected I remove the CENTER_HORIZONTAL rule and add a rule 'ALIGN_START' with a switch that is already positioned in the desired X coordinate. It works just fine. The problem occurs when View 1 is selected again and I switch from View 2 to View 1. In this situation I remove the ALIGN_START rule and add the CENTER_HORIZONTAL one. The thing is that tvAnchor remains aligned to the switch as if the ALIGN_START rule was not removed. I tried to get the direction of the layout, used requestLayout and other things that could think of, but nothing seems to remove that rule.
Did you check that there isn't coming some mystery values enabled??
I had case where is moved clockwidget place in layout
I did add ALIGN_PARENT_END and removed CENTER_IN_PARENT but when i set layout back i could not get clock widget centered.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mTextClockWidget.getLayoutParams();
p.addRule(RelativeLayout.ALIGN_PARENT_END, 1);
p.removeRule(RelativeLayout.CENTER_IN_PARENT);
mTextClockWidget.setLayoutParams(p);
Then noticed that from somewhere my layout params got ALIGN_PARENT_RIGHT enabled and when tried to remove ALIGN_PARENT_END and enable CENTER_IN_PARENT it didn't work. So i had to also add remove for ALIGN_PARENT_RIGHT to get it work.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mTextClockWidget.getLayoutParams();
p.removeRule(RelativeLayout.ALIGN_PARENT_END);
p.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
p.addRule(RelativeLayout.CENTER_IN_PARENT, 1);
mTextClockWidget.setLayoutParams(p);
I have an Android Flow layout hash_tag_layout
<org.apmem.tools.layouts.FlowLayout
android:id="#+id/hash_tag_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/view_padding"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin">
</org.apmem.tools.layouts.FlowLayout>
The problem is I cannot change the margins on dynamically added views.
int pixels = convertDensityPixelsToPixels(5);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(0,0,pixels,pixels); //<---<< This line has no effect
TextView tv1 = new TextView(ctx);
tv1.setPadding(pixels,pixels,pixels,pixels); //int left top right bottom
tv1.setBackground(ctx.getResources().getDrawable(R.drawable.hash_tag_bubble_format));//drawable
tv1.setText("# Asd");
tv1.setLayoutParams(lp);
layout.addView(tv1);
If I change hash_tag_layout layout to a regular linear layout, than I get margins!
<LinearLayout
android:id="#+id/hash_tag_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
So I am lead to conlude that Android Flow layout does not allow me to add margins to views added dynamically!
Any idea how to change the source code or find a way around this? Maybe add a transparent border around the dynamically added views?
Just change your LinearLayout.LayoutParams to FlowLayout.LayoutParams.
Here is an issue discussion on GitHub.
I see that you asked a question 3 years ago, but I have just faced the same problem :)
I add a view to the left of an existing view which is centred in parent. I would like the layout to update and centre both the view I added dynamically to the left of the existing view and the existing view.
I have previously looked at this question and tried to get the view to wrap_content after I have added the view which did not work using:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF, timePicker.getId());
params.addRule(RelativeLayout.CENTER_VERTICAL);
picker.setLayoutParams(params);
lytBottom.addView(picker);
RelativeLayout.LayoutParams existingParams = (RelativeLayout.LayoutParams) lytBottom.getLayoutParams();
existingParams.width = RelativeLayout.LayoutParams.WRAP_CONTENT;
and tried changing the visibility as per the top suggested comment. All the above did was wrap_content around the view originally there and completely ignores the dynamically added view.
Is there another way I could be approaching this to achieve the centering of both the new view and the old one while keeping the new view to the left of the old view?
The xml:
<android.support.percent.PercentRelativeLayout
android:id="#+id/lytBottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#+id/lytTop"
android:layout_centerHorizontal="true"
app:layout_heightPercent="30%">
<TimePicker
android:id="#+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:timePickerMode="spinner"/>
</android.support.percent.PercentRelativeLayout>
I'm trying to center a custom view in relative layout. This image rotates so it needs to be in the center of the layout so it doesn't go out of the layout bounds. Right now its displaying in the top left corner. Here is my code:
container = (RelativeLayout) findViewById(R.id.lay_container);
bmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.charlie_sheen);
rotate_view = new RotationView(this, bmap);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
rotate_view.setLayoutParams(params);
container.addView(rotate_view);
Here is my relative xml layout
<RelativeLayout
android:id="#+id/lay_container"
android:layout_width="200dip"
android:layout_height="200dip"
android:layout_alignParentRight="true"
android:layout_below="#+id/txt_1"
android:layout_marginRight="45dp"
android:layout_marginTop="56dp"
android:padding="10dip" />
Do you have any ideas? I know that there is probably a simple solution to this problmem, but I can't seem to find the answer. Setting the LayoutParameter to center should center the view in the layour right?
Thanks in advance for any help or suggestions
Overall the code to add the custom view looks correct. This may be a weak suggestion, but to rule out any issues that may have been cause by the view customization you could try modifying the code in one of two ways.
Option 1: Use the explicit form of addRule(), i.e.
params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
Option 2: Use the explicit form of addView() and don't set the params on the view itself, i.e.
//Omit the line above this one
container.addView(rotate_view, params);
Beyond that, perhaps some insight into the custom view, specifically how it measures itself (it's not trying to fill parent is it)?
HTH
Ok Devunwired I will do that.
Here is how I am centering the image now.
1) I am centering the image in my canvas using a BitmapDrawable setGravity(Gravity.CENTER) property.
2) I'm centering the RotationView in my Relative Layout:
<RelativeLayout
android:id="#+id/image_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/txt_1"
android:layout_centerHorizontal="true" >
<com.mobicartel.acceldatatester.RotationView
android:id="#+id/rotate_view"
android:layout_centerInParent="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</RelativeLayout>
I'll add the background and let you know. (Right now the image isn't displaying at all. Sometimes you have to take a step backward to take two in the right direction!)