Fix icon grid layout being bigger than needed but then not showing all contents. Also decrease layout overhead of same.

This commit is contained in:
dosiecki 2015-11-24 22:56:17 -08:00
parent d9f6c44c93
commit 0835921248
5 changed files with 149 additions and 164 deletions

View file

@ -117,7 +117,7 @@
android:layout_toRightOf="@id/comment_username"
android:paddingTop="2dp"
newsblur:flow="left"
newsblur:defaultImageSize="20" />
newsblur:imageViewSize="20" />
</RelativeLayout>

View file

@ -11,44 +11,44 @@
style="?rowItemHeaderBackground">
<RelativeLayout
android:id="@+id/row_item_feed_header"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="6dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
style="?rowItemFeedHeader">
android:id="@+id/row_item_feed_header"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="6dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
style="?rowItemFeedHeader">
<ImageView
android:id="@+id/reading_feed_icon"
android:layout_width="17dp"
android:layout_height="17dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dp"
android:layout_marginRight="5dp"
android:contentDescription="@string/description_row_folder_icon" />
android:id="@+id/reading_feed_icon"
android:layout_width="17dp"
android:layout_height="17dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dp"
android:layout_marginRight="5dp"
android:contentDescription="@string/description_row_folder_icon" />
<TextView
android:id="@+id/reading_feed_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/reading_feed_icon"
android:layout_centerVertical="true"
android:ellipsize="end"
android:lines="1"
android:textColor="@color/newsblur_blue"
android:textSize="12sp"
android:textStyle="bold" />
android:id="@+id/reading_feed_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/reading_feed_icon"
android:layout_centerVertical="true"
android:ellipsize="end"
android:lines="1"
android:textColor="@color/newsblur_blue"
android:textSize="12sp"
android:textStyle="bold" />
</RelativeLayout>
<View
android:id="@+id/item_feed_border"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/row_item_feed_header"
android:background="@color/darkgray"/>
android:id="@+id/item_feed_border"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/row_item_feed_header"
android:background="@color/darkgray"/>
<TextView
android:id="@+id/reading_item_title"
@ -90,9 +90,9 @@
android:layout_height="17dp"
android:layout_alignLeft="@id/reading_item_title"
android:layout_below="@id/reading_item_date"
android:layout_marginBottom="12dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -11,7 +11,7 @@
<View
android:id="@+id/center_filler"
android:layout_width="10dp"
android:layout_width="8dp"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="5dp"
style="?shareBarText"
android:textSize="11sp"
@ -34,7 +34,7 @@
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="16dp"
android:layout_marginRight="8dp"
style="?shareBarText"
android:textSize="11sp"
android:textStyle="bold" />
@ -42,7 +42,7 @@
<com.newsblur.view.FlowLayout
android:id="@+id/reading_social_commentimages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/center_filler"
android:layout_toRightOf="@id/comment_by" />
@ -51,10 +51,10 @@
xmlns:newsblur="http://schemas.android.com/apk/res/com.newsblur"
android:id="@+id/reading_social_shareimages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/shared_by"
android:layout_toRightOf="@+id/center_filler"
newsblur:flow="left" />
</RelativeLayout>
</RelativeLayout>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="flow" format="string" />
<attr name="defaultImageSize" format="integer" />
<attr name="imageViewSize" format="integer" />
<attr name="selectorFolderBackground" format="string" />
<attr name="selectorFeedBackground" format="string" />
<attr name="selectorRowFolderName" format="string" />
@ -32,6 +32,6 @@
<declare-styleable name="FlowLayout">
<attr name="flow" />
<attr name="defaultImageSize" />
<attr name="imageViewSize" />
</declare-styleable>
</resources>

View file

@ -1,8 +1,10 @@
package com.newsblur.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@ -11,44 +13,29 @@ import com.newsblur.R;
import com.newsblur.util.UIUtils;
/**
* A viewGroup that arranges child views in a similar way to text, with them laid
* out one line at a time and "wrapping" to the next line as needed. It handles ImageView children
* as special cases. It's a modified version of the code referenced below.
* A ViewGroup that arranges child views in a similar way to text, with them laid
* out one line at a time and "wrapping" to the next line as needed. Handles ImageView
* children as special case that should all be squares of the same size, for forming
* icon grids. Many iterations ago inspired by the code referenced below.
*
* @author Ryan Bateman / Henrik Gustafsson
* @see http://stackoverflow.com/questions/549451/line-breaking-widget-layout-for-android
*
*/
public class FlowLayout extends ViewGroup {
private int line_height;
private int defaultImageLength = 0;
private final int FLOW_RIGHT = 0;
private final int FLOW_LEFT = 1;
// By default, flow left to right
private int flowDirection = FLOW_RIGHT;
public static class LayoutParams extends ViewGroup.LayoutParams {
private final static int FLOW_RIGHT = 0;
private final static int FLOW_LEFT = 1;
private final static int DEFAULT_IMAGEVIEW_SIZE_DP = 25;
private final static int DEFAULT_CHILD_SPACING_DP = 3;
public final int horizontal_spacing;
public final int vertical_spacing;
/**
* @param horizontal_spacing Pixels between items, horizontally
* @param vertical_spacing Pixels between items, vertically
*/
public LayoutParams(int horizontal_spacing, int vertical_spacing) {
super(0, 0);
this.horizontal_spacing = horizontal_spacing;
this.vertical_spacing = vertical_spacing;
}
}
private final int flowDirection;
private final int imageViewSizePx;
private final int childSpacingPx;
public FlowLayout(Context context) {
super(context);
defaultImageLength = UIUtils.dp2px(context, 25);
flowDirection = FLOW_RIGHT;
imageViewSizePx = UIUtils.dp2px(context, DEFAULT_IMAGEVIEW_SIZE_DP);
childSpacingPx = UIUtils.dp2px(context, DEFAULT_CHILD_SPACING_DP);
}
public FlowLayout(Context context, AttributeSet attrs) {
@ -56,132 +43,130 @@ public class FlowLayout extends ViewGroup {
TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
String flowAttribute = styledAttributes.getString(R.styleable.FlowLayout_flow);
int defaultImageSizeAttribute = styledAttributes.getInt(R.styleable.FlowLayout_defaultImageSize, 25);
defaultImageLength = UIUtils.dp2px(context, defaultImageSizeAttribute);
if (!TextUtils.isEmpty(flowAttribute) && TextUtils.equals(flowAttribute, "left")) {
flowDirection = FLOW_LEFT;
flowDirection = FLOW_LEFT;
} else {
flowDirection = FLOW_RIGHT;
}
int imageViewSizeAttributeDp = styledAttributes.getInt(R.styleable.FlowLayout_imageViewSize, DEFAULT_IMAGEVIEW_SIZE_DP);
imageViewSizePx = UIUtils.dp2px(context, imageViewSizeAttributeDp);
childSpacingPx = UIUtils.dp2px(context, DEFAULT_CHILD_SPACING_DP);
styledAttributes.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
final int count = getChildCount();
int line_height = 0;
int xpos;
int ypos= getPaddingTop();
xpos = (flowDirection == FLOW_RIGHT) ? getPaddingLeft() : getWidth();
int childHeightMeasureSpec;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
int width = 0;
if ( (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) ||
(MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) ) {
width = MeasureSpec.getSize(widthMeasureSpec);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
throw new IllegalStateException("FlowLayout must have an expected width");
}
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childw;
if (child instanceof ImageView) {
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), defaultImageLength);
childw = defaultImageLength;
line_height = Math.max(line_height, defaultImageLength + lp.vertical_spacing);
} else {
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
childw = child.getMeasuredWidth();
line_height = Math.max(line_height, child.getMeasuredHeight() + lp.vertical_spacing);
}
if (flowDirection == FLOW_RIGHT && xpos + childw > width) {
xpos = getPaddingLeft();
ypos += line_height;
} else if (flowDirection == FLOW_LEFT && xpos - childw < 0) {
xpos = getWidth();
ypos += line_height;
}
if (flowDirection == FLOW_RIGHT) {
xpos += childw + lp.horizontal_spacing;
} else {
xpos -= childw + lp.horizontal_spacing;
int height = 0;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
height = MeasureSpec.getSize(heightMeasureSpec);
// even though we don't need to calculate height, we still need to tell all of our
// childern how to measure
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height - getPaddingTop() - getPaddingBottom(), MeasureSpec.AT_MOST);
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
if (!(child instanceof ImageView)) {
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
}
}
}
} else {
int line_height = 0;
int xpos = (flowDirection == FLOW_RIGHT) ? getPaddingLeft() : (width-getPaddingRight());
int ypos = getPaddingTop();
int childHeightMeasureSpec;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom(), MeasureSpec.AT_MOST);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
}
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
int childw;
int childh;
if (child instanceof ImageView) {
childw = imageViewSizePx;
childh = imageViewSizePx;
} else {
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
childw = child.getMeasuredWidth();
childh = child.getMeasuredHeight();
}
line_height = Math.max(line_height, childh);
if (flowDirection == FLOW_RIGHT && xpos + childw > (width-getPaddingRight())) {
xpos = getPaddingLeft();
ypos += line_height + childSpacingPx;
line_height = 0;
} else if (flowDirection == FLOW_LEFT && xpos - childw < getPaddingLeft()) {
xpos = width-getPaddingRight();
ypos += line_height + childSpacingPx;
line_height = 0;
}
if (flowDirection == FLOW_RIGHT) {
xpos += childw + childSpacingPx;
} else {
xpos -= childw + childSpacingPx;
}
}
}
}
this.line_height = line_height;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
height = ypos + line_height;
} else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
if (ypos + line_height < height) {
height = ypos + line_height;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
if (height > maxHeight) height = maxHeight;
}
}
setMeasuredDimension(width, height);
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
int defaultPadding = UIUtils.dp2px(getContext(), 3);
return new LayoutParams(defaultPadding, defaultPadding);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
if (p instanceof LayoutParams) {
return true;
}
return false;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
final int width = r - l;
int xpos = (flowDirection == FLOW_RIGHT) ? getPaddingLeft() : getWidth();
int line_height = 0;
int xpos = (flowDirection == FLOW_RIGHT) ? getPaddingLeft() : (width-getPaddingRight());
int ypos = getPaddingTop();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
int childw;
int childh;
if (child instanceof ImageView) {
childw = defaultImageLength;
childh = defaultImageLength;
} else {
childw = child.getMeasuredWidth();
childh = child.getMeasuredHeight();
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (flowDirection == FLOW_RIGHT && xpos + childw > width) {
xpos = getPaddingLeft();
ypos += line_height;
} else if (flowDirection == FLOW_LEFT && xpos - childw < 0) {
xpos = getWidth();
ypos += line_height;
int childw;
int childh;
if (child instanceof ImageView) {
childw = imageViewSizePx;
childh = imageViewSizePx;
} else {
childw = child.getMeasuredWidth();
childh = child.getMeasuredHeight();
}
line_height = Math.max(line_height, childh);
if (flowDirection == FLOW_RIGHT && xpos + childw > (width-getPaddingLeft())) {
xpos = getPaddingLeft();
ypos += line_height + childSpacingPx;
line_height = 0;
} else if (flowDirection == FLOW_LEFT && xpos - childw < getPaddingRight()) {
xpos = width-getPaddingRight();
ypos += line_height + childSpacingPx;
line_height = 0;
}
if (flowDirection == FLOW_RIGHT) {
child.layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + lp.horizontal_spacing;
child.layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + childSpacingPx;
} else {
child.layout(xpos - childw, ypos, xpos, ypos + childh);
xpos -= childw + lp.horizontal_spacing;
child.layout(xpos - childw, ypos, xpos, ypos + childh);
xpos -= childw + childSpacingPx;
}
}
}