Change row dimensions on scrolling ListView - android

I have a ListView and my each row in the list is a RelativeLayout with an ImageView and TextView. I want to change the dimensions of the RelativeLayout dynamically on scrolling of the list, such that the first and last row width is equal to screen width and the middle row width is half of the screen width. I am able to change the text size of the TextView dynamically using the following code:
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//Calculate height and width based on visible count items and position
final int viewHeight = height // calculated based on row position;
final int viewWidth = width // calculated based on row position;
for (int i = 0; i < visibleItemCount; i++) {
final RelativeLayout layout = (RelativeLayout) listView.getChildAt(i);
final ImageView imageView = (ImageView) layout.findViewById(R.id.icon);
final TextView time = (TextView) layout.findViewById(R.id.time);
time.post(new Runnable() {
#Override
public void run() {
time.setTextSize(viewHeight);
}
});
}
}
But I want to change the dimensions of the entire row layout dynamically on scrolling. Please check my code below. Any help appreciated.
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//Calculate height and width based on visible count items and position
final int viewHeight = height // calculated based on row position;
final int viewWidth = width // calculated based on row position;
for (int i = 0; i < visibleItemCount; i++) {
final RelativeLayout layout = (RelativeLayout) listView.getChildAt(i);
setLayoutDimensions(layout,viewHeight, viewWidth);
}
}
private void setLayoutDimensions(final RelativeLayout layout, final int height, final int width){
RelativeLayout.LayoutParams adaptLayout = new RelativeLayout.LayoutParams(width, height);
layout.setLayoutParams(adaptLayout);
}

Try to set the width and height of the relative layout like this:
LayoutParams params = layout.getLayoutParams();
params.width= width;
params.width= height;
layout.setLayoutParams(params);
you can convert your width and height to dp according to the device screen density using TypedValue.applyDimension method

Related

get ConstraintLayout height and width

I want to make a method that computes the margin values based on the parent's height and width. The code below outputs -1 for both height and width. How can I get the parent's height and width properly?
#RequiresApi(api = Build.VERSION_CODES.R)
public void setMarginsPercentages(Context context, #NotNull ConstraintLayout parent, #NotNull Object object, double leftPercentage, double topPercentage, double rightPercentage, double bottomPercentage) {
FrontEndObject item = getObjectType(object);
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(parent.getLayoutParams());
int height = params.height; //outputs -1
int width = params.width; //outputs -1
int left = (int) (leftPercentage * width);
int right = (int) (rightPercentage * width);
int top = (int) (topPercentage * height);
int bottom = (int) (bottomPercentage * height);
item.setMargins(parent, object, left, top, right, bottom);
}
There are couple problems here, the parms.height will give you this value (https://developer.android.com/reference/android/view/ViewGroup.LayoutParams#MATCH_PARENT), which is -1. Not the constraint layout's height in pixel you are looking for.
Also, You cannot use the width/height/getMeasuredWidth/getMeasuredHeight on a View before the system renders it (typically from onCreate/onResume). But you could set a listener, to get the value after the system calculate the pixel for the MATCH_PARENT.
Try this at your fragment's onViewCreated()
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
myView = view.findViewById(R.id.rtt); # your constraint layout
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int height = bottom - top;
int width = right - left;
Log.i("LOG", "height is" + height);
Log.i("LOG", "width is " + width);
}
});
}
Anyway, notice you only get this value after the view is rendered. At this point the view is already rendered, you might not be able to edit the margin. You might want to rethink your approach.

Gravity of a child TextView does not work with custom ViewGroup

I have the following classes:
public class MyGridView extends ViewGroup {
...
#Override
public void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
super.onSizeChanged(xNew, yNew, xOld, yOld);
// do calculations for drawing bounds of child views
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child;
Rect rect;
for (int i=0; i < getChildCount(); i++) {
child = getChildAt(i);
rect = getBoundsAtChildIndex(i)
child.layout(rect.left, rect.top, rect.right, rect.bottom);
}
}
...
}
AND
public class MyAdapter {
public void setMyGridView(MyGridView myGridView) {
// add a single TextView to my grid view
textView = createTextView(context);
addTextViewToGrid(textView);
container.add(textView);
}
private TextView createTextView(Context context) {
TextView textView = new TextView(context);
textView.setText("1");
textView.setTextColor(0xffffffff);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f);
textView.setTypeface(typeface);
textView.setGravity(Gravity.CENTER | Gravity.FILL);
// textView.setGravity(Gravity.RIGHT); // other tries to see gravity
// textView.setGravity(Gravity.FILL);
return textView;
}
private void addTextViewToGrid(TextView textView) {
myGridViewPtr.addView(textView, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
...
}
I have created a custom grid view and adapter, where its children draw to the screen to the correct size and location. However, their gravity, set in the createTextView() is not observed.
I can set a background image to the textView and see it fill its space in the grid.
In contrast, the text in textView always draws in its top left corner, and it always stays at the text size I set it at 12sp, rather than scale to fit using Gravity.FILL.
Preferably, the text would scale to fit and center within the textview.
EDIT
I have added the following method for onMeasure() in ViewGroup:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
doUpdateOnSizeChanged(width, height);
for (int i = 0; i < getChildCount(); i++)
getChildAt(i).measure((int) viewDim.x, (int) viewDim.y);
setMeasuredDimension(width, height);
}
The children are supposed to be the same height, width as each other. The android example code for ViewGroup is more sophisticated than I require. For instance, I am not getting the max of all children width, height.
For my onMeasure(), the child width, height in ViewDim is width, height integers that are computed in doUpdateOnSizeChanged to be less than getMeasuredWidth, getMeasuredHeight.
The result is now text aligns in the bottom-left corner of the TextView.
onMeasure needed minor corrections, basically needing to rely on MeasureSpec:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width, height;
int cWidth1, cHeight1;
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
doUpdateOnSizeChanged(width, height);
cWidth1 = (int)viewDim.x; cHeight1 = (int)viewDim.y;
measureChildren(MeasureSpec.makeMeasureSpec(cWidth1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(cHeight1, MeasureSpec.EXACTLY));
setMeasuredDimension(width, height);
}

Resize top view on listview scrolling

I have a layout above a list view which is at the bottom of the main layout.
When i scroll the list, i want to make the top layout smaller. i am trying now to do that using on list view scroll listener and change the layout parameters width and height.
The problem is that this procedure its not smoothly at all, eats a lot of resources.
How can i re-size the top view without using layout parameters (eating a lot of Resources) ?
that the scroll listener I set for the listview:
public class EndLessScrolling implements AbsListView.OnScrollListener {
private int amountViewInitDimension = 0;
public EndLessScrolling() {}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//amountView on scroll resize effect
if (firstVisibleItem < 5) {
View amountView = getActivity().findViewById(R.id.select_receiver_amount_parent);
if (amountView != null) {
ViewGroup.LayoutParams params = amountView.getLayoutParams();
if (amountViewInitDimension == 0) {
amountViewInitDimension = params.width;
}
params.width = amountViewInitDimension - firstVisibleItem * amountViewInitDimension / 10;
params.height = amountViewInitDimension - firstVisibleItem * amountViewInitDimension / 10;
receiverAmount.setTextSize(TypedValue.COMPLEX_UNIT_SP, amountTextSize - firstVisibleItem * zoomStep);
dollarSign.setTextSize(TypedValue.COMPLEX_UNIT_SP, dollarSignTextSize - firstVisibleItem * zoomStep / 2f);
amountView.setLayoutParams(params);
}
}
}
}
Have you seen this library? I think is what you want.
https://github.com/carlonzo/StikkyHeader

Textview gravity in custom ViewGroup

I have a custom view that extends ViewGroup and I don't know why but I can't center the text of my TextView vertically.
This is how I do it:
TextView myTextView = new TextView(mContext);
myTextView.setBackgroundColor(0xFFFF9900);
myTextView.layout(left, top, right, bottom);
myTextView.setGravity(Gravity.CENTER); // with this, the text is centered horizontally but is still on top. There is plenty of space below
this.addView(myTextView);
I have do this a lot of time on LinearLayout or RelativeLayout, I should have missed something but what?
Edit:
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Point centerOfView = new Point(this.getMeasuredWidth()/2, this.getMeasuredHeight()/2);
Log.d(TAG, "onLayout changed:"+changed+" buttonDiametre:"+buttonDiametre);
for(int n=0; n< this.getChildCount(); n++){
View v = getChildAt(n);
if (v instanceof TextView) {
v.layout(centerOfView.x-buttonDiametre/2, centerOfView.y-buttonDiametre/2, centerOfView.x+buttonDiametre/2, centerOfView.y+buttonDiametre/2);
ViewGroup.LayoutParams textViewParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
v.setLayoutParams(textViewParams);
TextView txt = (TextView)v;
txt.setGravity(Gravity.CENTER);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(TAG, "onMeasure");
int width = getMeasuredWidth();
int height = getMeasuredHeight();
buttonDiametre = (int) (this.getMeasuredWidth()/4);
Log.d(TAG, "buttonDiametre:"+buttonDiametre+" getChildCount:"+getChildCount());
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(buttonDiametre, buttonDiametre);
}
setMeasuredDimension(width, height);
}
With this try to override onMeasure and onLayout, I see no changes except that the text has lost it center horizontal align. The text is now on top left even with setGravity set to center.
Otherwise, my textbox that are in a square form display well on the different positions. I know i have put them in center but i animate them later to get in correct pposition.
You need to set your TextView height to MATCH_PARENT, then it will center text vertically, too:
TextView myTextView = new TextView(mContext);
myTextView.setBackgroundColor(0xFFFF9900);
myTextView.layout(left, top, right, bottom);
ViewGroup.LayoutParams textViewParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
myTextView.setLayoutParams(textViewParams);
myTextView.setGravity(Gravity.CENTER); // with this, the text is centered horizontally but is still on top. There is plenty of space below
this.addView(myTextView);

How can I get the coordinates and size of ImageView in LinearLayout

When I click the button,call drawDigit(),puzzleview is only a LinearLayout in Activity
protected void drawDigit(Canvas canvas, int digit) {
// TODO Auto-generated method stub
if(num < diff){
int x = tiles.get(num).getScrollX(); // get the X coordinate of ImageView,it's 0
int y = tiles.get(num).getScrollY(); // get the Y coordinate of ImageView,it's 0
float height = tiles.get(num).getHeight(); // height is 0
float width = tiles.get(num).getWidth(); // width is 0
background.setTextSize(height * 0.75f);
background.setStyle(Style.FILL);
background.setTextScaleX(width/height);
background.setTextAlign(Paint.Align.CENTER);
canvas.drawText(digit + "", x, y, background);
//num++;
}
}
How can I assign the ImageView in Layout to tiles,then get the coordinate and size?
You can try this :
//This is for Getting ImageView size that is fixed in layout
int imageHeight;
int imageWidth;
ImageView imageViewObj = (ImageView)findViewById(R.id.image_view_id);
ViewTreeObserver treeObsObj = imageViewObj.getViewTreeObserver();
treeObsObj.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
imageWidth= imageViewObj.getMeasuredWidth();
imageHeight = imageViewObj.getMeasuredHeight();
return true;
}
});
// Getting the size of the Image inside the ImageView and The size will differ based
**// on the image you placed inside the ImageView
ImageView imageObj = (ImageView)findViewById(R.id.image_view_id);
int imageWidth = imageObj.getWidth();
int imageHeight = imageObj.getHeight();

Categories

Resources