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" ><RelativeLayoutandroid:id="@+id/rl_category_title_bar_layout" android:layout_height="wrap_content" android:layout_width="match_parent" > <RelativeLayoutandroid:layout_height="50dp" android:layout_width="match_parent" > <TextViewandroid: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 paddingprivate int lineSpacing = 0; // the spacing between lines in flowlayoutList<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();}@Overrideprotected 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 linelineY += lineHeight + lineSpacing;lineUsed = mPaddingLeft + mPaddingRight;lineHeight = 0;}if (spaceHeight > lineHeight) {lineHeight = spaceHeight;}lineUsed += spaceWidth;}setMeasuredDimension(widthSize,heightMode == MeasureSpec.EXACTLY ? heightSize : lineY + lineHeight + mPaddingBottom);}@Overrideprotected 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 linelineNumList.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 linelineNumList.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 viewreturn;}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 relayoutcontinue;}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 relayoutcontinue;}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 viewreturn;}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 relayoutcontinue;}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 relayoutcontinue;}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);}}@Overrideprotected LayoutParams generateLayoutParams(LayoutParams p) {return new MarginLayoutParams(p);}@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs){return new MarginLayoutParams(getContext(), attrs);}@Overrideprotected 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;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return 0;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic 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() {@Overridepublic 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"> <LinearLayoutandroid:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical" > <RelativeLayoutandroid: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> <Viewstyle="@style/category_view_style" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayoutandroid:layout_height="match_parent"android:layout_width="match_parent"> <comskyball.addflowlayout.FlowLayoutandroid: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"/> <LinearLayoutandroid:id="@+id/ll_lv_category_add" style="@style/category_ll_style" android:layout_height="35dp" android:layout_below="@id/flow_layout_lv_category" > <ImageViewandroid:id="@+id/iv_lv_category_arrow" style="@style/category_iv_style" android:background="@drawable/arrow_down" /> <Viewstyle="@style/category_view_style" /></LinearLayout></RelativeLayout></ScrollView> </LinearLayout></RelativeLayout>以上所述是小编给大家介绍的Android 实现伸缩布局效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!