Changing RelativeLayout - the height changes but not width - android

I have a relative layout that will expand / collapse - so I increase/decrease the height when a user taps on it.
I'm using this code
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
params.height = intialExpandedHeight; // or initialHeight - based on the expand or collapse effect
params.width = screenWidht + 150; // or a screenWidht value when collapsed
view.setLayoutParams(params);
view.requestLayout();
The height of the layout changes and it works the way I want it to - the only problem is that the width is not changing. (it's the same every time)
Could you please tell me what seems to be the problem with my code? Why does the height changes but not width?

Related

can a custom RelativeLayout exceed parents height when defined as parents height?

I have the following structure within a view hierarchy
ScrollView
LinearLayout (horizontal)
- RelativeLayout (X)
-LinearLayout
-CustomView
- RelativeLayout
- RelativeLayout
- RelativeLayout
- RelativeLayout
- RelativeLayout
Here is a sample of it in the xml
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="#+id/linLayoutWrapper"
android:layout_width="match_parent"
android:layout_height="1080dp"
android:background="#color/white">
<!--- note this include is a <RelativeLayout> -->
<include
android:id="#+id/dg_axis"
layout="#layout/day_grid_axis"></include>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#color/grayBorder"></View>
<--- start of repetitive substructure which his higlighted in screen shot -->
<RelativeLayout
android:id="#+id/sundayColumn"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="1080dp">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
</LinearLayout>
<com.mynursesstation.views.DayView
android:id="#+id/sundayDayView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#color/grayBorder"></View>
<!--- repeat above sub structure 6 more times --->
</LinearLayout>
</ScrollView>
where the inner structure (X) is repeated for all other RelativeLayout siblings. The Linear Layout, RelativeLayouts
NOTE: (X) is shown highlighted in its unusual behavior in Red, where as its parent is the entire screen width and is delimited with the grey vertical line above it.
The RelativeLayouts would all be flush to the top of the Linear Layout if all of them were the same size (That is my experimental opinion which has yet to be proved). If one is bigger than the rest, then they by default align to the bottom. My question is, how can These children of the RelativeLayout's exceed their parent when they are defined by the parent? Could it be that I am programmatically creating views whose intrinsic heights exceed the height of their parents? What is android's official handling of this case? Does the view overflow like an HTML DOM element?
UPDATE:
On inspecting each RelativeLayout, my hypothesis that one of them exceeded 3240pixels was wrong. None of them do. Only there seems to be a top margin applied to some (Which would theoretically increase the height of its parent, being wrap_content) but it does not.
The definition of the RelativeLayout called CustomView, is a RelativeLayout within which are programmatically positioned relativelayouts. They are positioned within their parent as follows:
int pixels = (int) (height * scale + 0.5f);
pixels = (pixels + 4) / 5 * 5;
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(
columnWidth / maxConflicts,
pixels));
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.addRule(RelativeLayout.ALIGN_PARENT_START);
start = cal2.get(Calendar.HOUR_OF_DAY);
height = start > 0 ? start * 44.000000000f + (start - 1) : start * 44.00000000f;
height += cal2.get(Calendar.MINUTE) / 60.00000000000f;
pixels = (int) (height * scale + 0.5f);
if (offsetAmount != null){
params.setMargins( (columnWidth / maxConflicts) * offsetAmount, pixels, 0, 0);
} else {
params.setMargins(0, pixels, 0, 0);
}
relativeLayout.setLayoutParams(params);
However there is never a case where the top margin of the relativeLayout above plus the height of the of the relativeLayout exceeds 1080dp. I verify this dynamically by logging the height of the CustomView DayView with the following code:
columnHeight = MeasureSpec.getSize(heightMeasureSpec);
which always logs out as 3240 pixels which at a scale of 3 is exactly 1080dp.
So this eliminates the possibility that one of the DayView exceeds 1080 and that is why not all the children of the top level LinearLayout are not flush to its top. However, I still cannot comprehend what could be causing this behavior. All elements programmatically added to the DayView are alignTop to their parent and are positioned with a vertically margin which, with the height of the view being programmatically added` never exceeds 1080dp.
Notice that the red views have a mysterious mTop added even though their dynamic height is 1080dp. mTop + 1080dp > 1080dp yet there parent is 1080dp (it is wrap_content) !
Take a good look at the view which is flush. It also has the same height but has a zero mTop. I don't understand why this is or how can be possible.
enter image description here
UPDATE Saturday:
Good News! i have narrowed down the problem to a subview of a subview, which when omitted, does not cause this strange inconsistency in my layout logic / intention. The culprit is a <TextView> which is programmatically added to the two types of events which are programmatically added <RelativeLayout>s added to DayView. when both types of views have textviews added as subviews it breaks the view hierarchy. When only one is present, the views present as intended. Here is the code for programmatically laying out the calendar events the entirety of which consist of all the subviews of a DayView:
private void createEventLayout(CalendarEvent e, Integer offsetAmount, int maxConflicts) {
final float scale = getContext().getResources().getDisplayMetrics().density;
int idForMyView = e.assignmentId > 0 ? e.assignmentId : -e.conflictId;
RelativeLayout relativeLayout = new RelativeLayout(getContext());
relativeLayout.setId(idForMyView);
Calendar cal2 = Calendar.getInstance();
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
cal2.setTime(e.startDate);
Calendar cal3 = Calendar.getInstance();
cal3.setTimeZone(TimeZone.getTimeZone("UTC"));
cal3.setTime(e.endDate);
float start = cal2.get(Calendar.HOUR_OF_DAY);
start += cal2.get(Calendar.MINUTE) / 60.0000000f;
float end = cal3.get(Calendar.HOUR_OF_DAY);
end += cal3.get(Calendar.MINUTE) / 60.00000000f;
float height = (end - start) * 45.0000000f;
int pixels = (int) (height * scale + 0.5f);
pixels = (pixels + 4) / 5 * 5;
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(
columnWidth / maxConflicts,
pixels));
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.addRule(RelativeLayout.ALIGN_PARENT_START);
start = cal2.get(Calendar.HOUR_OF_DAY);
height = start > 0 ? start * 44.000000000f + (start - 1) : start * 44.00000000f;
height += cal2.get(Calendar.MINUTE) / 60.00000000000f;
pixels = (int) (height * scale + 0.5f);
if (offsetAmount != null){
params.setMargins( (columnWidth / maxConflicts) * offsetAmount, pixels, 0, 0);
} else {
params.setMargins(0, pixels, 0, 0);
}
relativeLayout.setLayoutParams(params);
if (e.assignmentId > 0){
// company name
TextView tv = new TextView(getContext());
tv.setId(idForMyView);
tv.setText(e.companyName);
LayoutParams tvParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
tvParams.setMargins(0,0,0,0);
tv.setLayoutParams(tvParams);
RelativeLayout.LayoutParams companyNameParams = (RelativeLayout.LayoutParams) tv.getLayoutParams();
tv.setTextColor(Color.parseColor("#ffffff"));
tv.setTypeface(null, Typeface.BOLD);
companyNameParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
//time of assignment / conflict
TextView tvTime = new TextView(getContext());
tvTime.setTextColor(Color.parseColor("#ffffff"));
SimpleDateFormat sdf = new SimpleDateFormat("h:mm a");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String startTime = sdf.format(e.startDate);
String endTime = sdf.format(e.endDate);
tvTime.setText(startTime + " - " + endTime);
tvTime.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
RelativeLayout.LayoutParams timeParams = (RelativeLayout.LayoutParams) tvTime.getLayoutParams();
timeParams.addRule(RelativeLayout.BELOW, idForMyView);
relativeLayout.addView(tv); // ALSO this will break if present with the other kind
relativeLayout.addView(tvTime); // this too
relativeLayout.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.gradient_background_home));
relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final int assignmentId = view.getId();
if (assignmentId > 0) {
Intent intent = new Intent(getContext(), AssignmentDetailActivity.class);
intent.putExtra(getContext().getString(R.string.extra_assignment_id), assignmentId);
getContext().startActivity(intent);
}
}
});
} else {
final CalendarEvent event = e;
relativeLayout.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.conflict));
if (isConflictMode && e.isAllDay == 1){
TextView tv = new TextView(getContext());
tv.setId(idForMyView);
tv.setText(ALL_DAY_TEXT);
LayoutParams tvParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
tvParams.setMargins(0,0,0,0);
tv.setLayoutParams(tvParams);
RelativeLayout.LayoutParams companyNameParams = (RelativeLayout.LayoutParams) tv.getLayoutParams();
tv.setTextColor(Color.parseColor("#ffffff"));
tv.setTypeface(null, Typeface.BOLD);
companyNameParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.calendar_small_font));
relativeLayout.addView(tv); //THIS will break the layout logic
}
}
this.addView(relativeLayout);
return;
}
I tried making sure the <TextView> is clipped by its parent by setting
tv.setGravity(Gravity.CLIP_HORIZONTAL | Gravity.CLIP_VERTICAL)
when I inspect it in the view it appears that it is clipping exactly to the bounds of the tv, yet, something seems to be exceeding the height of its parent based on the fact that when the <TextViews> are gone everything addes up, but when they are present, there seems to be too much vertical content.
So my problem was that i was assigning the same id to the <RelativeLayout> which was the particular CalendarEvent as well as to the children of this view, the <TextViews>. This created circular logic which referred to the parent and child which caused the views to not properly by aligned, I think specifically with the BELOW requirement of one of the textViews, being essentially made to be below itself. By creating a unique id with View.generateId() each time I created a <TextView> then the intended layout was made possible.

Android Resize selected item in GridView

I have a grid view displaying a number of ImageView with different background colors. Is it possible to scale just the selected item without affecting the placement of the other items in the GridView? Something like below?
I have tried setting the layout params on the underlying view that is returned when an item is clicked, but that seems to be chopping off part of the resized item and it not centering the selected item.
int newDimension = Utility.dpToPx(100);
float measuredWidth = view.getMeasuredWidth();
float measuredHeight = view.getMeasuredHeight();
GridView.LayoutParams layoutParams = (GridView.LayoutParams) view.getLayoutParams();
view.setPivotX(newDimension / 2);
view.setPivotY(newDimension / 2);
layoutParams.width = newDimension;
layoutParams.height = newDimension;
view.setLayoutParams(layoutParams);
close try calling, gridView.getItemAtPosition(position) and it will return your view do your operation then

How to set height in Android grid programmaticaly according to width?

I have gridview which contains 2 columns. The width is set to fill available space.
I need height to be set to specific size according to width, because in every screen the width dimension is different, I can't set height in xml as constant. I need to set ratio, so height should be about 1.5 * width.
Thanks
You can set Height, but you want to get Width First.
You told 2 columns of grid so understand phone half of your phone width
Display display = getWindowManager().getDefaultDisplay();
int imgWidth = display.getWidth() / 2;
int imgHeight = (int)(imgWidth * 1.5f);
You get height of that.Now you can set your Grid View Width and Height
LayoutParams lp = HERE_YOUR_VIEW.getLayoutParams();
lp.width = imgWidth;
lp.height = imgHeight ;
HERE_YOUR_VIEW.setLayoutParams(lp);

How to add an ImageView to the center of the screen, by ratio

My code:
Display display = getWindowManager().getDefaultDisplay();
final int width = display.getWidth();
final int height = display.getHeight();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(200,200);
relativeLayout.addView(img1,params);
params.leftMargin = width/2;
params.topMargin = height/2;
setContentView(relativeLayout);
Could somebody help me to fit my img1 to the center of the screen, at every resolution?
I think that the display.getwidth value is not associated with params.leftmargin.
Please instruct me to get the margin value to any use by dividing it.
try this
RelativeLayout.LayoutParams params =new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
img1.setLayoutParams(params);
relativeLayout.addView(img1);
EDIT : if u want to add more views then u should create layoutparams for every view and use addRule method I m just giving u an example how to place a view under a view u can place that view right , left or above accoridngly change this RelativeLayout.ALIGN_BOTTOM and u can use RelativeLayout.LAYOUT_BELOW instead of RelativeLayout.ALIGN_BOTTOM
p.addRule(RelativeLayout.ALIGN_BOTTOM, ur_view.getId());
if u create it in xml it will be much more easier
if u want to set margin for any view do something like this
p.setMargins(left margin, top margin, right margin, bottom margin);
left margin, top margin, right margin, bottom margin are Integer
value, which value u want to set for ur view

How to change LayoutParams on change view size

I have ImageView. I change margins and size of ImageVew on set new bitmap. For example, user click button, I set bitmap to ImageView and change params (this is code from my own view):
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
p.leftMargin = (int) ((pw - lw) / 2f);
_topMargin = (int) ((ph - lh) / 2f);
lp.topMargin = _topMargin;
lp.width = lw;
lp.height = lh;
requestLayout();
All work. But also I want change params, if change size parent view of my ImageView. If I try use code on change params from this event - nothing todo (ImageView don't change params).
How I can fix this issue?
I see now one way: on change parent size, I don't change ImageView params, only set some internal boolean flag. After finish parent changing, I change my ImageView params. But I don't know, what parent event I need watch, after which I can change my ImageView params.
My solution.
I use this method.
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
lp.leftMargin = (int) ((pw - lw) / 2f);
_topMargin = (int) ((ph - lh) / 2f);
lp.topMargin = _topMargin;
lp.width = lw;
lp.height = lh;
setLayoutParams(lp);//<---set layout params
requestLayout();
After changing layout params you need to set it back.

Categories

Resources