Flow layout issues - android

I am using this flow layout class to arrange dynamically created TextView in multiple lines but i have got following issues:
The height of this layout doesn't behave as WRAP_CONTENT(as shown in
image given in the link).
I am placing this layout toRightOf an another static
TextViews(To,Cc). It leaves a margin in left equal to TextView width
in every line(as shown in image given in the link).
I want to delete this margin when content switches to next line. How to resolve this?
Any help would be appreciated.
public class FlowLayout extends ViewGroup
{
private int paddingHorizontal;
public FlowLayout(Context context)
{
super(context);
init();
}
public FlowLayout(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
paddingHorizontal = getResources().getDimensionPixelSize(R.dimen.flowlayout_horizontal_padding);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
int myWidth = resolveSize(100, widthMeasureSpec);
int wantedHeight = 0;
for (int i = 0; i < getChildCount(); i++)
{
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE)
{
continue;
}
child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width), getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth)
{
childLeft = getPaddingLeft();
childTop += lineHeight;
lineHeight = childHeight;
}
childLeft += childWidth + paddingHorizontal;
}
wantedHeight += childTop + lineHeight + getPaddingBottom();
setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
int myWidth = right - left;
for (int i = 0; i < getChildCount(); i++)
{
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE)
{
continue;
}
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth)
{
childLeft = getPaddingLeft();
childTop += lineHeight;
lineHeight = childHeight;
}
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
childLeft += childWidth + paddingHorizontal;
}
}
}
I am using it in my xml like this:
<RelativeLayout
android:id="#+id/main_relative_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="#+id/To_textView_wrapper_relative_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/To_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="#string/to"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp" />
<PackageName.FlowLayout
android:id="#+id/flow_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/To_textView" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/Cc_textView_wrapper_relative_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/To_textView_wrapper_relative_layout" >
<TextView
android:id="#+id/PhoneNo_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="#string/cc"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp" />
<PackageName.FlowLayout
android:id="#+id/flow_container1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/Cc_textView" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/Bcc_textView_wrapper_relative_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PhoneNo_textView_wrapper_relative_layout" >
<TextView
android:id="#+id/Bcc_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="#string/bcc"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp" />
<PackageName.FlowLayout
android:id="#+id/flow_container2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/Bcc_textView" />
</RelativeLayout>
</RelativeLayout>

Related

Draw from a view is not drawing in exact location in Android

I am drawing a view in canvas with existing views. But it draw below the view. Not exactly on the view.
public class MyView extends View {
Paint paint;
ViewGroup viewGroup;
Context context;
public MyView(Context context, ViewGroup viewGroup) {
super(context);
this.viewGroup = viewGroup;
this.context = context;
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paint = new Paint();
paint.setColor(context.getResources().getColor(R.color.gray));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Point point = getLocationOnScreen(child);
Rect rect = new Rect();
int x = point.x;
int y = point.y;
rect.left = x;
rect.top = y;
rect.right = x + child.getWidth();
rect.bottom = y + child.getHeight();
canvas.drawRect(rect, paint);
}
/*for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Rect rect = new Rect();
rect.left = child.getLeft();
rect.top = child.getTop();
rect.bottom = child.getBottom();
rect.right = child.getRight();
canvas.drawRect(rect, paint);
}*/
}
public static Point getLocationOnScreen(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Point(location[0], location[1]);
}
}
My MainActivity:
public class MainActivity extends AppCompatActivity {
ConstraintLayout constraintLayout;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
constraintLayout = findViewById(R.id.parent_view);
imageView = findViewById(R.id.item_profile_img);
imageView.post(() -> {
ViewGroup viewGroup = (ViewGroup) constraintLayout;
constraintLayout.addView(new MyView(MainActivity.this,viewGroup));
});
}
}
activity_main.xml:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="HardcodedText,MissingConstraints"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
tools:ignore="HardcodedText,MissingConstraints"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:id="#+id/parent_view">
<ImageView
android:id="#+id/item_profile_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_launcher_background"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,MissingConstraints" />
<TextView
android:id="#+id/item_student_name_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="Student name"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="#+id/item_profile_img" />
<TextView
android:id="#+id/item_student_college"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student college"
app:layout_constraintStart_toEndOf="#+id/item_profile_img"
app:layout_constraintTop_toBottomOf="#+id/item_student_name_title" />
<TextView
android:id="#+id/item_student_specialization"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student specialization"
app:layout_constraintStart_toEndOf="#+id/item_profile_img"
app:layout_constraintTop_toBottomOf="#+id/item_student_college" />
<TextView
android:id="#+id/item_student_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student description"
app:layout_constraintTop_toBottomOf="#+id/item_profile_img"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Please review my code and let me know where I did mistake.
Try This
change you're for loop inside onDraw() like this
for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Rect rect = new Rect();
// int x = point.x;
// int x = point.x;
int x = (int) child.getX() - dpToPx(20);
int y = (int) child.getY() - dpToPx(20);
rect.left = x;
rect.top = y;
rect.right = x + child.getWidth();
rect.bottom = y + child.getHeight();
canvas.drawRect(rect, paint);
}
use a view.getX() and view.getY() it returns proper x and y position of view minus value 20 is the padding of your parent view
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

Scrollview with big custom view and smaller textviews

I am trying to make a scrollable layout, where I would have a single bigger custom view at the start and dynamic amount of smaller TextViews after it.
Like this:
|-----|---Start of devices screen
| |
| | -Custom view 1
| |
|-----|
| |---TextView & End of devices screen
|-----|
|-----|
| |
|-----|
The custom view is a view where I do some drawing in onDraw().
I have been trying to fiddle with the onMeasure() method, layout_height and layout_weight properties, but I am unable to get a satisfactory result. I always end up with a unscrollable layout or one without the custom view. Only way I have been able to get the functionality is by setting the custom view's height to some 'dp' value, but I would like it leave the same physical amount of space in the botto of the screen.
Is something like this possible with the tools Android provides, or would this need some custom view for the scrolling too? How would I go about implementing this?
Edit: To clarify, I need the first element I have in the ScrollView to initially either fill the whole visible area of the ScrollView or leave a small space under it that is constant on every device.
Use Flow Layout In place of your custom layout
find flow layout implementation link
https://docs.google.com/file/d/0B_VKZCqEnHblNDdiY2UxODgtYWNhNS00MmU4LWE4NDMtZjQ1OWI5MDMxZTVh/edit?num=50&sort=name&layout=list&pli=1#
package com.example.android.layout;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class FlowLayout extends ViewGroup {
private int mHorizontalSpacing;
private int mVerticalSpacing;
private Paint mPaint;
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
try {
mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
} finally {
a.recycle();
}
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(0xffff0000);
mPaint.setStrokeWidth(2.0f);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;
int width = 0;
int height = getPaddingTop();
int currentWidth = getPaddingLeft();
int currentHeight = 0;
boolean breakLine = false;
boolean newLine = false;
int spacing = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
spacing = mHorizontalSpacing;
if (lp.horizontalSpacing >= 0) {
spacing = lp.horizontalSpacing;
}
if (growHeight && (breakLine || currentWidth + child.getMeasuredWidth() > widthSize)) {
height += currentHeight + mVerticalSpacing;
currentHeight = 0;
width = Math.max(width, currentWidth - spacing);
currentWidth = getPaddingLeft();
newLine = true;
} else {
newLine = false;
}
lp.x = currentWidth;
lp.y = height;
currentWidth += child.getMeasuredWidth() + spacing;
currentHeight = Math.max(currentHeight, child.getMeasuredHeight());
breakLine = lp.breakLine;
}
if (!newLine) {
height += currentHeight;
width = Math.max(width, currentWidth - spacing);
}
width += getPaddingRight();
height += getPaddingBottom();
setMeasuredDimension(resolveSize(width, widthMeasureSpec),
resolveSize(height, heightMeasureSpec));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
}
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean more = super.drawChild(canvas, child, drawingTime);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y - 4.0f, x, y + 4.0f, mPaint);
canvas.drawLine(x, y, x + lp.horizontalSpacing, y, mPaint);
canvas.drawLine(x + lp.horizontalSpacing, y - 4.0f, x + lp.horizontalSpacing, y + 4.0f, mPaint);
}
if (lp.breakLine) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x, y + 6.0f, mPaint);
canvas.drawLine(x, y + 6.0f, x + 6.0f, y + 6.0f, mPaint);
}
return more;
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
#Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
#Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p.width, p.height);
}
public static class LayoutParams extends ViewGroup.LayoutParams {
int x;
int y;
public int horizontalSpacing;
public boolean breakLine;
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout_LayoutParams);
try {
horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, -1);
breakLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_breakLine, false);
} finally {
a.recycle();
}
}
public LayoutParams(int w, int h) {
super(w, h);
}
}
}
<resources>
<declare-styleable name="FlowLayout">
<attr name="horizontalSpacing" format="dimension" />
<attr name="verticalSpacing" format="dimension" />
</declare-styleable>
<declare-styleable name="FlowLayout_LayoutParams">
<attr name="layout_breakLine" format="boolean" />
<attr name="layout_horizontalSpacing" format="dimension" />
</declare-styleable>
</resources>

Android custom view into scrollView not show

I am trying to put a custom view into scrollView. This is my custom view MyCustomLayout.java
public class MyCustomLayout extends ViewGroup {
private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10;
private int mMaxChildWidth = 0;
private int mMaxChildHeight = 0;
public MyCustomLayout(Context context) {
super(context, null);
}
public MyCustomLayout(Context context, AttributeSet attrs) {
super(context, attrs, 0);
}
public MyCustomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mMaxChildWidth = 0;
mMaxChildHeight = 0;
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());
mMaxChildHeight = Math.max(mMaxChildHeight, child.getMeasuredHeight());
}
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
mMaxChildWidth, MeasureSpec.EXACTLY);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
mMaxChildHeight, MeasureSpec.EXACTLY);
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
setMeasuredDimension(
resolveSize(mMaxChildWidth, widthMeasureSpec),
resolveSize(mMaxChildHeight, heightMeasureSpec));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int width = r - l;
int height = b - t;
final int count = getChildCount();
// Calculate the number of visible children.
int visibleCount = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
++visibleCount;
}
if (visibleCount == 0) {
return;
}
int bestSpaceDifference = Integer.MAX_VALUE;
int spaceDifference;
int hSpace = 0;
int vSpace = 0;
int cols = 1;
int rows;
while (true) {
rows = (visibleCount - 1) / cols + 1;
hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));
vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));
spaceDifference = Math.abs(vSpace - hSpace);
if (rows * cols != visibleCount) {
spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER;
}
if (spaceDifference < bestSpaceDifference) {
bestSpaceDifference = spaceDifference;
if (rows == 1) {
break;
}
} else {
--cols;
rows = (visibleCount - 1) / cols + 1;
hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));
vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));
break;
}
++cols;
}
hSpace = Math.max(0, hSpace);
vSpace = Math.max(0, vSpace);
width = (width - hSpace * (cols + 1)) / cols;
height = (height - vSpace * (rows + 1)) / rows;
int left, top;
int col, row;
int visibleIndex = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
row = visibleIndex / cols;
col = visibleIndex % cols;
left = hSpace * (col + 1) + width * col;
top = vSpace * (row + 1) + height * row;
child.layout(left, top,
(hSpace == 0 && col == cols - 1) ? r : (left + width),
(vSpace == 0 && row == rows - 1) ? b : (top + height));
++visibleIndex;
}
}
}
When I use in a LinearLayout with those xml code. It works fine.
<com.crazyCoder.androiddeshboard.MyCustomLayout
android:id="#+id/layout_custom"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#f8f9fe" >
</com.crazyCoder.androiddeshboard.MyCustomLayout>
But when I put into a scrollView like this
<ScrollView
android:id="#+id/scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffd9f4">
<com.crazyCoder.androiddeshboard.MyCustomLayout
android:id="#+id/layout_custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f8f9fe" >
</com.crazyCoder.androiddeshboard.MyCustomLayout>
</ScrollView>
The custom view overlapping by the scrollView. The output like this.
ScrollView Output
Please Help me. Thanks in advance.
Try put FrameLayout in ScrollView and put MyCustomLatyout in FrameLayout.
<ScrollView
android:id="#+id/scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffd9f4">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.crazyCoder.androiddeshboard.MyCustomLayout
android:id="#+id/layout_custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f8f9fe" >
</com.crazyCoder.androiddeshboard.MyCustomLayout>
</FrameLayout>
</ScrollView>

Implement Chips without search functionality

I want to implement chip something like this:
chip
But since I've a predefined Array Adapter & just need to put its values into this chip & I want to set these chips to a Textview or simply View. I've tried many chip libraries but all of them gave some kind of error while adding to dependencies.
I just need to implement chips for the look of the app & not search functionality so can anyone help me in this & if you have any better ideas then please feel free to share.
Finally I did it like this with the help of a nine patch image chip.9.png & FlowLayout:
MainActivity:
LinearLayout llTemp = new LinearLayout(this);
llTemp.setOrientation(LinearLayout.HORIZONTAL);
llTemp.setBackgroundResource(R.drawable.chip);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llTemp.setLayoutParams(params);
llTemp.setGravity(Gravity.CENTER_VERTICAL);
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
tv.setPadding(0, 0, 5, 0);
tv.setText("Some text");
CircularImageView iv = new CircularImageView(this);
LinearLayout.LayoutParams ivParams = new LinearLayout.LayoutParams(50, 50);
ivParams.setMargins(0, 0, 5, 0);
iv.setLayoutParams(ivParams);
iv.setBorderWidth(0);
Picasso.with(this).load(IMAGE_LINK + IMAGE_FILE).into(iv);
ImageView ivCloseBtn = new ImageView(this);
ivCloseBtn.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
ivCloseBtn.setPadding(2, 2, 2, 2);
ivCloseBtn.setBackgroundResource(R.drawable.icon_close);
FlowLayout.java:
public class FlowLayout extends ViewGroup {
private int paddingHorizontal;
private int paddingVertical;
public FlowLayout(Context context) {
super(context);
init();
}
public FlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paddingHorizontal = getResources().getDimensionPixelSize(R.dimen.flowlayout_horizontal_padding);
paddingVertical = getResources().getDimensionPixelSize(R.dimen.flowlayout_vertical_padding);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
// 100 is a dummy number, widthMeasureSpec should always be EXACTLY for FlowLayout
int myWidth = resolveSize(100, widthMeasureSpec);
int wantedHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
// let the child measure itself
child.measure(
getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
// lineheight is the height of current line, should be the height of the highest view
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth) {
// wrap this line
childLeft = getPaddingLeft();
childTop += paddingVertical + lineHeight;
lineHeight = childHeight;
}
childLeft += childWidth + paddingHorizontal;
}
wantedHeight += childTop + lineHeight + getPaddingBottom();
setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
int myWidth = right - left;
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth) {
childLeft = getPaddingLeft();
childTop += paddingVertical + lineHeight;
lineHeight = childHeight;
}
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
childLeft += childWidth + paddingHorizontal;
}
}}
& then in Main Activity: flowLayout.addView(llTemp)
& flow layout within xml file(mainactivity):
<ScrollView android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<com.example.FlowLayout
android:id="#+id/fl"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
Final Product: final_chip_image

Hide child during onLayout

I am trying to hide a child in a view during onLayout. The problem is the postInvalidate is not recalling onLayout after i hide the child
public class EllipseFlowLayout extends ViewGroup {
private int paddingHorizontal;
private int paddingVertical;
private int mMaxLines = -1;
private EllipseView mEllipse;
private View ellipseView;
private int numHidden;
private boolean mEllipseRemoved = true;
public EllipseFlowLayout(Context context) {
super(context);
init();
}
public void setMaxLines(int max) {
mMaxLines = max;
}
public EllipseFlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EllipseFlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paddingHorizontal = getResources().getDimensionPixelSize(R.dimen.flowlayout_horizontal_padding);
paddingVertical = getResources().getDimensionPixelSize(R.dimen.flowlayout_vertical_padding);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
int numLines = 1;
// 100 is a dummy number, widthMeasureSpec should always be EXACTLY for FlowLayout
int myWidth = resolveSize(MeasureSpec.EXACTLY, widthMeasureSpec);
int wantedHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE || child.getTag() == GONE) {
continue;
}
// let the child measure itself
child.measure(
getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
// lineheight is the height of current line, should be the height of the heightest view
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth) {
// wrap this line
childLeft = getPaddingLeft();
childTop += paddingVertical + lineHeight;
lineHeight = childHeight;
numLines++;
Log.d("TEST", "measure" + numLines);
}
childLeft += childWidth + paddingHorizontal;
}
wantedHeight += childTop + lineHeight + getPaddingBottom();
setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
}
#Override
public void addView(View child) {
//super.addView(child);
if (mEllipseRemoved) {
addEllipseView();
}
super.addView(child, getChildCount() - 1);
}
public void setEllipseView(EllipseView ellipse) {
mEllipse = ellipse;
ellipseView = mEllipse.getView();
}
#Override
public void removeAllViews() {
mEllipseRemoved = true;
super.removeAllViews();
}
private void addEllipseView() {
mEllipseRemoved = false;
if (ellipseView.getParent() != null) {
((ViewGroup) ellipseView.getParent()).removeView(ellipseView);
}
ellipseView.setVisibility(View.GONE);
addView(ellipseView);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
int lineHeight = 0;
int myWidth = right - left;
int lineNum = 1;
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if (childWidth + childLeft + getPaddingRight() > myWidth) {
childLeft = getPaddingLeft();
childTop += paddingVertical + lineHeight;
lineHeight = childHeight;
lineNum++;
Log.d("TEST", "layout" + lineNum);
}
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
childLeft += childWidth + paddingHorizontal;
}
if (lineNum > mMaxLines) {
// if (ellipseView.getVisibility() == View.GONE) {
// ellipseView.setVisibility(VISIBLE);
// }
//Skip the last view which is the hidden one
int at = numHidden;
if (at < getChildCount() && getChildAt(at) != null) {
View child = getChildAt(at);
numHidden++;
if (child.getVisibility() == View.VISIBLE) {
child.setVisibility(View.GONE);
child.setTag(GONE);
requestLayout();
}
}
if (mEllipse.getCount() != numHidden) {
mEllipse.setEllipseSize(numHidden);
}
}
}
/**
* Was removed so semi untested but leaving for possible use later
*
* #param max max children
*/
public void setMaxChildren(int max) {
}
}
Hide the views in onDraw remember to call this.setWillNotDraw(false);

Categories

Resources