Android Open Source - TechDissected Flow Layout






From Project

Back to project page TechDissected.

License

The source code is released under:

Apache License

If you think the Android project TechDissected listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.pkmmte.techdissected.view;
/*  w  ww.j a v a2  s .co m*/
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;
import com.pkmmte.techdissected.R;

public class FlowLayout extends ViewGroup {
  public static final int HORIZONTAL = 0;
  public static final int VERTICAL = 1;
  private int horizontalSpacing = 0;
  private int verticalSpacing = 0;
  private int orientation = 0;
  private boolean debugDraw = false;

  public FlowLayout(Context context) {
    super(context);

    this.readStyleParameters(context, null);
  }

  public FlowLayout(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);

    this.readStyleParameters(context, attributeSet);
  }

  public FlowLayout(Context context, AttributeSet attributeSet, int defStyle) {
    super(context, attributeSet, defStyle);

    this.readStyleParameters(context, attributeSet);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - this.getPaddingRight() - this.getPaddingLeft();
    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec) - this.getPaddingTop() - this.getPaddingBottom();

    int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
    int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

    int size;
    int mode;

    if (orientation == HORIZONTAL) {
      size = sizeWidth;
      mode = modeWidth;
    } else {
      size = sizeHeight;
      mode = modeHeight;
    }

    int lineThicknessWithSpacing = 0;
    int lineThickness = 0;
    int lineLengthWithSpacing = 0;
    int lineLength;

    int prevLinePosition = 0;

    int controlMaxLength = 0;
    int controlMaxThickness = 0;

    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() == GONE) {
        continue;
      }

      LayoutParams lp = (LayoutParams) child.getLayoutParams();

      child.measure(
        getChildMeasureSpec(widthMeasureSpec, this.getPaddingLeft() + this.getPaddingRight(), lp.width),
        getChildMeasureSpec(heightMeasureSpec, this.getPaddingTop() + this.getPaddingBottom(), lp.height)
      );

      int hSpacing = this.getHorizontalSpacing(lp);
      int vSpacing = this.getVerticalSpacing(lp);

      int childWidth = child.getMeasuredWidth();
      int childHeight = child.getMeasuredHeight();

      int childLength;
      int childThickness;
      int spacingLength;
      int spacingThickness;

      if (orientation == HORIZONTAL) {
        childLength = childWidth;
        childThickness = childHeight;
        spacingLength = hSpacing;
        spacingThickness = vSpacing;
      } else {
        childLength = childHeight;
        childThickness = childWidth;
        spacingLength = vSpacing;
        spacingThickness = hSpacing;
      }

      lineLength = lineLengthWithSpacing + childLength;
      lineLengthWithSpacing = lineLength + spacingLength;

      boolean newLine = lp.newLine || (mode != MeasureSpec.UNSPECIFIED && lineLength > size);
      if (newLine) {
        prevLinePosition = prevLinePosition + lineThicknessWithSpacing;

        lineThickness = childThickness;
        lineLength = childLength;
        lineThicknessWithSpacing = childThickness + spacingThickness;
        lineLengthWithSpacing = lineLength + spacingLength;
      }

      lineThicknessWithSpacing = Math.max(lineThicknessWithSpacing, childThickness + spacingThickness);
      lineThickness = Math.max(lineThickness, childThickness);

      int posX;
      int posY;
      if (orientation == HORIZONTAL) {
        posX = getPaddingLeft() + lineLength - childLength;
        posY = getPaddingTop() + prevLinePosition;
      } else {
        posX = getPaddingLeft() + prevLinePosition;
        posY = getPaddingTop() + lineLength - childHeight;
      }
      lp.setPosition(posX, posY);

      controlMaxLength = Math.max(controlMaxLength, lineLength);
      controlMaxThickness = prevLinePosition + lineThickness;
    }

        /* need to take paddings into account */
    if (orientation == HORIZONTAL) {
      controlMaxLength += getPaddingLeft() + getPaddingRight();
      controlMaxThickness += getPaddingBottom() + getPaddingTop();
    } else {
      controlMaxLength += getPaddingBottom() + getPaddingTop();
      controlMaxThickness += getPaddingLeft() + getPaddingRight();
    }

    if (orientation == HORIZONTAL) {
      this.setMeasuredDimension(resolveSize(controlMaxLength, widthMeasureSpec), resolveSize(controlMaxThickness, heightMeasureSpec));
    } else {
      this.setMeasuredDimension(resolveSize(controlMaxThickness, widthMeasureSpec), resolveSize(controlMaxLength, heightMeasureSpec));
    }
  }

  private int getVerticalSpacing(LayoutParams lp) {
    int vSpacing;
    if (lp.verticalSpacingSpecified()) {
      vSpacing = lp.verticalSpacing;
    } else {
      vSpacing = this.verticalSpacing;
    }
    return vSpacing;
  }

  private int getHorizontalSpacing(LayoutParams lp) {
    int hSpacing;
    if (lp.horizontalSpacingSpecified()) {
      hSpacing = lp.horizontalSpacing;
    } else {
      hSpacing = this.horizontalSpacing;
    }
    return hSpacing;
  }

  @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);
    this.drawDebugInfo(canvas, child);
    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 attributeSet) {
    return new LayoutParams(getContext(), attributeSet);
  }

  @Override
  protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
    return new LayoutParams(p);
  }

  private void readStyleParameters(Context context, AttributeSet attributeSet) {
    TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout);
    try {
      horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
      verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
      orientation = a.getInteger(R.styleable.FlowLayout_orientation, HORIZONTAL);
      debugDraw = a.getBoolean(R.styleable.FlowLayout_debugDraw, false);
    } finally {
      a.recycle();
    }
  }

  private void drawDebugInfo(Canvas canvas, View child) {
    if (!debugDraw) {
      return;
    }

    Paint childPaint = this.createPaint(0xffffff00);
    Paint layoutPaint = this.createPaint(0xff00ff00);
    Paint newLinePaint = this.createPaint(0xffff0000);

    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, x + lp.horizontalSpacing, y, childPaint);
      canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y - 4.0f, x + lp.horizontalSpacing, y, childPaint);
      canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y + 4.0f, x + lp.horizontalSpacing, y, childPaint);
    } else if (this.horizontalSpacing > 0) {
      float x = child.getRight();
      float y = child.getTop() + child.getHeight() / 2.0f;
      canvas.drawLine(x, y, x + this.horizontalSpacing, y, layoutPaint);
      canvas.drawLine(x + this.horizontalSpacing - 4.0f, y - 4.0f, x + this.horizontalSpacing, y, layoutPaint);
      canvas.drawLine(x + this.horizontalSpacing - 4.0f, y + 4.0f, x + this.horizontalSpacing, y, layoutPaint);
    }

    if (lp.verticalSpacing > 0) {
      float x = child.getLeft() + child.getWidth() / 2.0f;
      float y = child.getBottom();
      canvas.drawLine(x, y, x, y + lp.verticalSpacing, childPaint);
      canvas.drawLine(x - 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
      canvas.drawLine(x + 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
    } else if (this.verticalSpacing > 0) {
      float x = child.getLeft() + child.getWidth() / 2.0f;
      float y = child.getBottom();
      canvas.drawLine(x, y, x, y + this.verticalSpacing, layoutPaint);
      canvas.drawLine(x - 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
      canvas.drawLine(x + 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
    }

    if (lp.newLine) {
      if (orientation == HORIZONTAL) {
        float x = child.getLeft();
        float y = child.getTop() + child.getHeight() / 2.0f;
        canvas.drawLine(x, y - 6.0f, x, y + 6.0f, newLinePaint);
      } else {
        float x = child.getLeft() + child.getWidth() / 2.0f;
        float y = child.getTop();
        canvas.drawLine(x - 6.0f, y, x + 6.0f, y, newLinePaint);
      }
    }
  }

  private Paint createPaint(int color) {
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(color);
    paint.setStrokeWidth(2.0f);
    return paint;
  }

  public static class LayoutParams extends ViewGroup.LayoutParams {
    private static int NO_SPACING = -1;
    private int x;
    private int y;
    private int horizontalSpacing = NO_SPACING;
    private int verticalSpacing = NO_SPACING;
    private boolean newLine = false;

    public LayoutParams(Context context, AttributeSet attributeSet) {
      super(context, attributeSet);
      this.readStyleParameters(context, attributeSet);
    }

    public LayoutParams(int width, int height) {
      super(width, height);
    }

    public LayoutParams(ViewGroup.LayoutParams layoutParams) {
      super(layoutParams);
    }

    public boolean horizontalSpacingSpecified() {
      return horizontalSpacing != NO_SPACING;
    }

    public boolean verticalSpacingSpecified() {
      return verticalSpacing != NO_SPACING;
    }

    public void setPosition(int x, int y) {
      this.x = x;
      this.y = y;
    }

    private void readStyleParameters(Context context, AttributeSet attributeSet) {
      TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout_LayoutParams);
      try {
        horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, NO_SPACING);
        verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_verticalSpacing, NO_SPACING);
        newLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_newLine, false);
      } finally {
        a.recycle();
      }
    }
  }
}




Java Source Code List

com.pkmmte.techdissected.ApplicationTest.java
com.pkmmte.techdissected.activity.ArticleActivity.java
com.pkmmte.techdissected.activity.MainActivity.java
com.pkmmte.techdissected.activity.SearchActivity.java
com.pkmmte.techdissected.adapter.AuthorAdapter.java
com.pkmmte.techdissected.adapter.CreditsLibraryAdapter.java
com.pkmmte.techdissected.adapter.FeedAdapter.java
com.pkmmte.techdissected.adapter.NavDrawerAdapter.java
com.pkmmte.techdissected.adapter.SettingsAdapter.java
com.pkmmte.techdissected.fragment.AboutFragment.java
com.pkmmte.techdissected.fragment.ArticleFragment.java
com.pkmmte.techdissected.fragment.FavoritesFragment.java
com.pkmmte.techdissected.fragment.FeedFragment.java
com.pkmmte.techdissected.fragment.SettingsFragment.java
com.pkmmte.techdissected.model.Author.java
com.pkmmte.techdissected.model.CreditsLibraryItem.java
com.pkmmte.techdissected.model.ListBuilder.java
com.pkmmte.techdissected.model.SettingsItem.java
com.pkmmte.techdissected.util.Base64DecoderException.java
com.pkmmte.techdissected.util.Base64.java
com.pkmmte.techdissected.util.Constants.java
com.pkmmte.techdissected.util.Dialogs.java
com.pkmmte.techdissected.util.IabException.java
com.pkmmte.techdissected.util.IabHelper.java
com.pkmmte.techdissected.util.IabResult.java
com.pkmmte.techdissected.util.Inventory.java
com.pkmmte.techdissected.util.Purchase.java
com.pkmmte.techdissected.util.RoundTransform.java
com.pkmmte.techdissected.util.Security.java
com.pkmmte.techdissected.util.SkuDetails.java
com.pkmmte.techdissected.util.Utils.java
com.pkmmte.techdissected.view.BakedBezierInterpolator.java
com.pkmmte.techdissected.view.CustomShareActionProvider.java
com.pkmmte.techdissected.view.FlowLayout.java
com.pkmmte.techdissected.view.HeaderGridView.java
com.pkmmte.techdissected.view.PkDrawerLayout.java
com.pkmmte.techdissected.view.PkScrollView.java
com.pkmmte.techdissected.view.PkSwipeRefreshLayout.java
com.pkmmte.techdissected.view.StickyScrollView.java
com.pkmmte.techdissected.view.SwipeProgressBar.java