栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android 实现伸缩布局效果示例代码

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap

Android 实现伸缩布局效果示例代码

最近项目实现下面的图示的效果,本来想用listview+gridview实现,但是貌似挺麻烦的于是就用flowlayout 来addview实现添加伸缩的效果,实现也比较简单。

mainActivity 布局



  
     
     
     
   
    

自定义布局flowlayout

package comskyball.addflowlayout;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class FlowLayout extends ViewGroup {
  private Context mContext;
  private int usefulWidth; // the space of a line we can use(line's width minus the sum of left and right padding
  private int lineSpacing = 0; // the spacing between lines in flowlayout
  List childList = new ArrayList();
  List lineNumList = new ArrayList();
  public FlowLayout(Context context) {
    this(context, null);
  }
  public FlowLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    TypedArray mTypedArray = context.obtainStyledAttributes(attrs,
 R.styleable.FlowLayout);
    lineSpacing = mTypedArray.getDimensionPixelSize(
 R.styleable.FlowLayout_lineSpacing, 0);
    mTypedArray.recycle();
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int mPaddingLeft = getPaddingLeft();
    int mPaddingRight = getPaddingRight();
    int mPaddingTop = getPaddingTop();
    int mPaddingBottom = getPaddingBottom();
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int lineUsed = mPaddingLeft + mPaddingRight;
    int lineY = mPaddingTop;
    int lineHeight = 0;
    for (int i = 0; i < this.getChildCount(); i++) {
      View child = this.getChildAt(i);
      if (child.getVisibility() == GONE) {
 continue;
      }
      int spaceWidth = 0;
      int spaceHeight = 0;
      LayoutParams childLp = child.getLayoutParams();
      if (childLp instanceof MarginLayoutParams) {
 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, lineY);
 MarginLayoutParams mlp = (MarginLayoutParams) childLp;
 spaceWidth = mlp.leftMargin + mlp.rightMargin;
 spaceHeight = mlp.topMargin + mlp.bottomMargin;
      } else {
 measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
      int childWidth = child.getMeasuredWidth();
      int childHeight = child.getMeasuredHeight();
      spaceWidth += childWidth;
      spaceHeight += childHeight;
      if (lineUsed + spaceWidth > widthSize) {
 //approach the limit of width and move to next line
 lineY += lineHeight + lineSpacing;
 lineUsed = mPaddingLeft + mPaddingRight;
 lineHeight = 0;
      }
      if (spaceHeight > lineHeight) {
 lineHeight = spaceHeight;
      }
      lineUsed += spaceWidth;
    }
    setMeasuredDimension(
 widthSize,
 heightMode == MeasureSpec.EXACTLY ? heightSize : lineY + lineHeight + mPaddingBottom
    );
  }
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int mPaddingLeft = getPaddingLeft();
    int mPaddingRight = getPaddingRight();
    int mPaddingTop = getPaddingTop();
    int lineX = mPaddingLeft;
    int lineY = mPaddingTop;
    int lineWidth = r - l;
    usefulWidth = lineWidth - mPaddingLeft - mPaddingRight;
    int lineUsed = mPaddingLeft + mPaddingRight;
    int lineHeight = 0;
    int lineNum = 0;
    lineNumList.clear();
    for (int i = 0; i < this.getChildCount(); i++) {
      View child = this.getChildAt(i);
      if (child.getVisibility() == GONE) {
 continue;
      }
      int spaceWidth = 0;
      int spaceHeight = 0;
      int left = 0;
      int top = 0;
      int right = 0;
      int bottom = 0;
      int childWidth = child.getMeasuredWidth();
      int childHeight = child.getMeasuredHeight();
      LayoutParams childLp = child.getLayoutParams();
      if (childLp instanceof MarginLayoutParams) {
 MarginLayoutParams mlp = (MarginLayoutParams) childLp;
 spaceWidth = mlp.leftMargin + mlp.rightMargin;
 spaceHeight = mlp.topMargin + mlp.bottomMargin;
 left = lineX + mlp.leftMargin;
 top = lineY + mlp.topMargin;
 right = lineX + mlp.leftMargin + childWidth;
 bottom = lineY + mlp.topMargin + childHeight;
      } else {
 left = lineX;
 top = lineY;
 right = lineX + childWidth;
 bottom = lineY + childHeight;
      }
      spaceWidth += childWidth;
      spaceHeight += childHeight;
      if (lineUsed + spaceWidth > lineWidth) {
 //approach the limit of width and move to next line
 lineNumList.add(lineNum);
 lineY += lineHeight + lineSpacing;
 lineUsed = mPaddingLeft + mPaddingRight;
 lineX = mPaddingLeft;
 lineHeight = 0;
 lineNum = 0;
 if (childLp instanceof MarginLayoutParams) {
   MarginLayoutParams mlp = (MarginLayoutParams) childLp;
   left = lineX + mlp.leftMargin;
   top = lineY + mlp.topMargin;
   right = lineX + mlp.leftMargin + childWidth;
   bottom = lineY + mlp.topMargin + childHeight;
 } else {
   left = lineX;
   top = lineY;
   right = lineX + childWidth;
   bottom = lineY + childHeight;
 }
      }
      child.layout(left, top, right, bottom);
      lineNum ++;
      if (spaceHeight > lineHeight) {
 lineHeight = spaceHeight;
      }
      lineUsed += spaceWidth;
      lineX += spaceWidth;
    }
    // add the num of last line
    lineNumList.add(lineNum);
  }
  
  public void relayoutToCompress() {
    int childCount = this.getChildCount();
    if (0 == childCount) {
      //no need to sort if flowlayout has no child view
      return;
    }
    int count = 0;
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (v instanceof BlankView) {
 //BlankView is just to make childs look in alignment, we should ignore them when we relayout
 continue;
      }
      count++;
    }
    View[] childs = new View[count];
    int[] spaces = new int[count];
    int n = 0;
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (v instanceof BlankView) {
 //BlankView is just to make childs look in alignment, we should ignore them when we relayout
 continue;
      }
      childs[n] = v;
      LayoutParams childLp = v.getLayoutParams();
      int childWidth = v.getMeasuredWidth();
      if (childLp instanceof MarginLayoutParams) {
 MarginLayoutParams mlp = (MarginLayoutParams) childLp ;
 spaces[n] = mlp.leftMargin + childWidth + mlp.rightMargin;
      } else {
 spaces[n] = childWidth;
      }
      n++;
    }
    int[] compressSpaces = new int[count];
    for (int i = 0; i < count; i++) {
      compressSpaces[i] = spaces[i] > usefulWidth ? usefulWidth : spaces[i];
    }
    sortToCompress(childs, compressSpaces);
    this.removeAllViews();
    for (View v : childList) {
      this.addView(v);
    }
    childList.clear();
  }
  private void sortToCompress(View[] childs, int[] spaces) {
    int childCount = childs.length;
    int[][] table = new int[childCount + 1][usefulWidth + 1];
    for (int i = 0; i < childCount +1; i++) {
      for (int j = 0; j < usefulWidth; j++) {
 table[i][j] = 0;
      }
    }
    boolean[] flag = new boolean[childCount];
    for (int i = 0; i < childCount; i++) {
      flag[i] = false;
    }
    for (int i = 1; i <= childCount; i++) {
      for (int j = spaces[i-1]; j <= usefulWidth; j++) {
 table[i][j] = (table[i-1][j] > table[i-1][j-spaces[i-1]] + spaces[i-1]) ? table[i-1][j] : table[i-1][j-spaces[i-1]] + spaces[i-1];
      }
    }
    int v = usefulWidth;
    for (int i = childCount ; i > 0 && v >= spaces[i-1]; i--) {
      if (table[i][v] == table[i-1][v-spaces[i-1]] + spaces[i-1]) {
 flag[i-1] = true;
 v = v - spaces[i - 1];
      }
    }
    int rest = childCount;
    View[] restArray;
    int[] restSpaces;
    for (int i = 0; i < flag.length; i++) {
      if (flag[i] == true) {
 childList.add(childs[i]);
 rest--;
      }
    }
    if (0 == rest) {
      return;
    }
    restArray = new View[rest];
    restSpaces = new int[rest];
    int index = 0;
    for (int i = 0; i < flag.length; i++) {
      if (flag[i] == false) {
 restArray[index] = childs[i];
 restSpaces[index] = spaces[i];
 index++;
      }
    }
    table = null;
    childs = null;
    flag = null;
    sortToCompress(restArray, restSpaces);
  }
  
  public void relayoutToAlign() {
    int childCount = this.getChildCount();
    if (0 == childCount) {
      //no need to sort if flowlayout has no child view
      return;
    }
    int count = 0;
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (v instanceof BlankView) {
 //BlankView is just to make childs look in alignment, we should ignore them when we relayout
 continue;
      }
      count++;
    }
    View[] childs = new View[count];
    int[] spaces = new int[count];
    int n = 0;
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (v instanceof BlankView) {
 //BlankView is just to make childs look in alignment, we should ignore them when we relayout
 continue;
      }
      childs[n] = v;
      LayoutParams childLp = v.getLayoutParams();
      int childWidth = v.getMeasuredWidth();
      if (childLp instanceof MarginLayoutParams) {
 MarginLayoutParams mlp = (MarginLayoutParams) childLp ;
 spaces[n] = mlp.leftMargin + childWidth + mlp.rightMargin;
      } else {
 spaces[n] = childWidth;
      }
      n++;
    }
    int lineTotal = 0;
    int start = 0;
    this.removeAllViews();
    for (int i = 0; i < count; i++) {
      if (lineTotal + spaces[i] > usefulWidth) {
 int blankWidth = usefulWidth - lineTotal;
 int end = i - 1;
 int blankCount = end - start;
 if (blankCount >= 0) {
   if (blankCount > 0) {
     int eachBlankWidth = blankWidth / blankCount;
     MarginLayoutParams lp = new MarginLayoutParams(eachBlankWidth, 0);
     for (int j = start; j < end; j++) {
this.addView(childs[j]);
BlankView blank = new BlankView(mContext);
this.addView(blank, lp);
     }
   }
   this.addView(childs[end]);
   start = i;
   i --;
   lineTotal = 0;
 } else {
   this.addView(childs[i]);
   start = i + 1;
   lineTotal = 0;
 }
      } else {
 lineTotal += spaces[i];
      }
    }
    for (int i = start; i < count; i++) {
      this.addView(childs[i]);
    }
  }
  
  public void relayoutToCompressAndAlign(){
    this.relayoutToCompress();
    this.relayoutToAlign();
  }
  
  public void specifyLines(int line_num) {
    int childNum = 0;
    if (line_num > lineNumList.size()) {
      line_num = lineNumList.size();
    }
    for (int i = 0; i < line_num; i++) {
      childNum += lineNumList.get(i);
    }
    List viewList = new ArrayList();
    for (int i = 0; i < childNum; i++) {
      viewList.add(getChildAt(i));
    }
    removeAllViews();
    for (View v : viewList) {
      addView(v);
    }
  }
  @Override
  protected LayoutParams generateLayoutParams(LayoutParams p) {
    return new MarginLayoutParams(p);
  }
  @Override
  public LayoutParams generateLayoutParams(AttributeSet attrs)
  {
    return new MarginLayoutParams(getContext(), attrs);
  }
  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new MarginLayoutParams(super.generateDefaultLayoutParams());
  }
  class BlankView extends View {
    public BlankView(Context context) {
      super(context);
    }
  }
}

adapter

package comskyball.addflowlayout;
import java.util.ArrayList;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.baseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class CategoryLvAdapter extends baseAdapter {
  public Context context;
  public ArrayList list;
  public boolean isMore=true;
  public CategoryLvAdapter(Context context,ArrayList list) {
    this.context=context;
    this.list=list;
  }
  @Override
  public int getCount() {
    return list.size();
  }
  @Override
  public Object getItem(int position) {
    return 0;
  }
  @Override
  public long getItemId(int position) {
    return 0;
  }
  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder=null;
    if(convertView==null){
      convertView=View.inflate(context, R.layout.lv_category_item, null);
      viewHolder=new ViewHolder();
      viewHolder.iv_lv_category_img=(ImageView) convertView.findViewById(R.id.iv_lv_category_img);
      viewHolder.tv_lv_category=(TextView) convertView.findViewById(R.id.tv_lv_category);
      viewHolder.flow_layout_lv_category=(FlowLayout) convertView.findViewById(R.id.flow_layout_lv_category);
      viewHolder.ll_lv_category_add=(LinearLayout) convertView.findViewById(R.id.ll_lv_category_add);
      viewHolder.iv_lv_category_arrow=(ImageView) convertView.findViewById(R.id.iv_lv_category_arrow);
      convertView.setTag(viewHolder);
    }else{
      viewHolder=(ViewHolder) convertView.getTag();
    }
//   ImageLoader.getInstance().displayImage(AppConfig.APP_URL+list.get(position).getImg(),viewHolder.iv_lv_category_img,App.normalOption);
    viewHolder.tv_lv_category.setText(list.get(position).getCate_name());
    viewHolder.iv_lv_category_arrow.setBackgroundResource(R.drawable.arrow_down);
    viewHolder.flow_layout_lv_category.removeAllViews();
    Utils.addflow(context,6, list.get(position).getNext(),viewHolder.flow_layout_lv_category);
    final FlowLayout flowLayoutLvCategory = viewHolder.flow_layout_lv_category;
    final ImageView ivLvCategoryArrow = viewHolder.iv_lv_category_arrow;
    viewHolder.ll_lv_category_add.setonClickListener(new onClickListener() {
      @Override
      public void onClick(View v) {
 if(isMore){
   isMore=false;
   flowLayoutLvCategory.removeAllViews();
   Utils.addflow(context,list.get(position).getNext().size(), list.get(position).getNext(),flowLayoutLvCategory);
   ivLvCategoryArrow.setBackgroundResource(R.drawable.arrow_up);
 }else{
   isMore=true;
   flowLayoutLvCategory.removeAllViews();
   Utils.addflow(context,6, list.get(position).getNext(),flowLayoutLvCategory);
   ivLvCategoryArrow.setBackgroundResource(R.drawable.arrow_down);
 }
      }
    }); 
    return convertView; 
  }
  public class ViewHolder{
    public ImageView iv_lv_category_img;
    public TextView tv_lv_category;
    public FlowLayout flow_layout_lv_category;
    public LinearLayout ll_lv_category_add;
    public ImageView iv_lv_category_arrow;
  }
}

adapter item布局



   
     


     
     
     



  
  
 
 
      
   

以上所述是小编给大家介绍的Android 实现伸缩布局效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对考高分网网站的支持!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/160262.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号