首页 > 系统 > Android > 正文

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

2019-12-12 04:06:02
字体:
来源:转载
供稿:网友

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

mainActivity 布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout   xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"   >  <RelativeLayout      android:id="@+id/rl_category_title_bar_layout"     android:layout_height="wrap_content"     android:layout_width="match_parent"     >     <RelativeLayout        android:layout_height="50dp"       android:layout_width="match_parent"       >     <TextView        android:id="@+id/tv_category_title"       android:layout_height="50dp"       android:layout_width="wrap_content"       android:text="分类"       android:textSize="18sp"       android:layout_centerInParent="true"       android:gravity="center"       />     </RelativeLayout>   </RelativeLayout>    <ListView       android:id="@+id/lv_category_menu"       android:layout_height="match_parent"       android:layout_width="match_parent"       /></LinearLayout>

自定义布局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<View> childList = new ArrayList();  List<Integer> 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);  }  /**   * resort child elements to use lines as few as possible   */  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);  }  /**   * add some blank view to make child elements look in alignment   */  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]);    }  }  /**   * use both of relayout methods together   */  public void relayoutToCompressAndAlign(){    this.relayoutToCompress();    this.relayoutToAlign();  }  /**   * cut the flowlayout to the specified num of lines   * @param line_num   */  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<View> viewList = new ArrayList<View>();    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<Category> list;  public boolean isMore=true;  public CategoryLvAdapter(Context context,ArrayList<Category> 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布局

<?xml version="1.0" encoding="utf-8"?><RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto"  android:layout_width="match_parent"  android:layout_height="match_parent"  >   <LinearLayout      android:layout_height="wrap_content"     android:layout_width="match_parent"     android:orientation="vertical"     >     <RelativeLayout        android:layout_height="35dp"       android:layout_width="match_parent"       >       <ImageView         android:id="@+id/iv_lv_category_img"          style="@style/category_iv_left_style"         />       <TextView         android:id="@+id/tv_lv_category"         style="@style/category_tv_style"         android:text="衣食"         android:layout_toRightOf="@id/iv_lv_category_img"         />     </RelativeLayout>     <View        style="@style/category_view_style"       />     <ScrollView       android:layout_width="match_parent"       android:layout_height="match_parent"       >       <RelativeLayout        android:layout_height="match_parent"        android:layout_width="match_parent"        >       <comskyball.addflowlayout.FlowLayout        android:id="@+id/flow_layout_lv_category"        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:lineSpacing="10dp"        app:maxLine="3"        android:background="#F0F0F0"        android:layout_marginTop="5dp"        />       <LinearLayout          android:id="@+id/ll_lv_category_add"         style="@style/category_ll_style"         android:layout_height="35dp"         android:layout_below="@id/flow_layout_lv_category"         >         <ImageView            android:id="@+id/iv_lv_category_arrow"           style="@style/category_iv_style"           android:background="@drawable/arrow_down"           />         <View            style="@style/category_view_style"           />        </LinearLayout>        </RelativeLayout>      </ScrollView>   </LinearLayout></RelativeLayout>

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表