android 实现伸缩布局效果

来源:互联网 发布:php sqlite3 安装 编辑:程序博客网 时间:2024/05/16 06:58

最近项目实现下面的图示的效果,本来想用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>
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑中毒了打不开软件怎么办 剑三程序不兼容怎么办 玩无主之地卡怎么办 平台老板跑路了怎么办 qq在苹果下载不了怎么办 下载速度快上传速度慢怎么办 苹果7开网页慢怎么办 为什么浏览器下载视频速度慢怎么办 机连WLAN网速慢怎么办 会声会影卸载后无法重新安装怎么办 电视空间不足无法卸载怎么办 堡垒之夜下载慢怎么办 手机网盘下载速度慢怎么办插件 笔记本电脑显示连接不可用怎么办 蓝魔手机充电慢怎么办 360f4手机充电慢怎么办 vivo卡了怎么办小窍门 白色衣服用84泡后变黄怎么办 用祛斑霜脱皮了怎么办 用祛斑霜脸一直蜕皮怎么办 吃热的就流鼻涕怎么办 键盘qaz失灵其他都没事怎么办 时时彩代理抓了怎么办 6p升级ios11卡顿怎么办 微信弄没了又换号了怎么办 快手账号异常请去激活怎么办 九游账号被转移怎么办 绝地求生刺激战场闪退怎么办 qq回执编号忘了怎么办 电脑开机要用户名和密码怎么办 电脑忘记用户名和密码怎么办 微信账号密码忘了怎么办 开发者账号密保忘记怎么办 华为账号忘记密保问题怎么办 fiyme账号忘记密保怎么办 id忘了密保问题怎么办 vivo账号密码忘记了怎么办 步步高账号密码忘了怎么办 步步高手机账号密码忘了怎么办 康佳电视通行证忘了怎么办 尚游通行证忘了怎么办