Android – LinearLayout水平与包装儿童

是否有一个属性来设置Android的LinearLayout,使其能够正确包装子控件?

意思 – 我有可以改变的孩子数量,并想横向排列他们,如:

示例:Control1,Control2,Control3 ...

我通过设置:

 ll.setOrientation(LinearLayout.HORIZONTAL);
 foreach(儿童c)
   ll.addView(C);

但是,如果我有大量的孩子,最后一个被切断,而不是下一个线路。

任何想法如何可以解决?

这应该是你想要的:

import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; /** * * @author RAW */ public class FlowLayout extends ViewGroup { private int line_height; public static class LayoutParams extends ViewGroup.LayoutParams { public final int horizontal_spacing; public final int vertical_spacing; /** * @param horizontal_spacing Pixels between items, horizontally * @param vertical_spacing Pixels between items, vertically */ public LayoutParams(int horizontal_spacing, int vertical_spacing) { super(0, 0); this.horizontal_spacing = horizontal_spacing; this.vertical_spacing = vertical_spacing; } } public FlowLayout(Context context) { super(context); } public FlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED); final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom(); final int count = getChildCount(); int line_height = 0; int xpos = getPaddingLeft(); int ypos = getPaddingTop(); int childHeightMeasureSpec; if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); } else { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec); final int childw = child.getMeasuredWidth(); line_height = Math.max(line_height, child.getMeasuredHeight() + lp.vertical_spacing); if (xpos + childw > width) { xpos = getPaddingLeft(); ypos += line_height; } xpos += childw + lp.horizontal_spacing; } } this.line_height = line_height; if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) { height = ypos + line_height; } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { if (ypos + line_height < height) { height = ypos + line_height; } } setMeasuredDimension(width, height); } @Override protected ViewGroup.LayoutParams generateDefaultLayoutParams() { return new LayoutParams(1, 1); // default of 1px spacing } @Override protected android.view.ViewGroup.LayoutParams generateLayoutParams( android.view.ViewGroup.LayoutParams p) { return new LayoutParams(1, 1, p); } @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { if (p instanceof LayoutParams) { return true; } return false; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); final int width = r - l; int xpos = getPaddingLeft(); int ypos = getPaddingTop(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final int childw = child.getMeasuredWidth(); final int childh = child.getMeasuredHeight(); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (xpos + childw > width) { xpos = getPaddingLeft(); ypos += line_height; } child.layout(xpos, ypos, xpos + childw, ypos + childh); xpos += childw + lp.horizontal_spacing; } } } } 

和XML文件

 /* you must write your package name and class name */ <org.android.FlowLayout android:id="@+id/flow_layout" android:layout_marginLeft="5dip" android:layout_width="fill_parent" android:layout_height="wrap_content"/> 

对于需要这种行为的人:

 private void populateLinks(LinearLayout ll, ArrayList<Sample> collection, String header) { Display display = getWindowManager().getDefaultDisplay(); int maxWidth = display.getWidth() - 10; if (collection.size() > 0) { LinearLayout llAlso = new LinearLayout(this); llAlso.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); llAlso.setOrientation(LinearLayout.HORIZONTAL); TextView txtSample = new TextView(this); txtSample.setText(header); llAlso.addView(txtSample); txtSample.measure(0, 0); int widthSoFar = txtSample.getMeasuredWidth(); for (Sample samItem : collection) { TextView txtSamItem = new TextView(this, null, android.R.attr.textColorLink); txtSamItem.setText(samItem.Sample); txtSamItem.setPadding(10, 0, 0, 0); txtSamItem.setTag(samItem); txtSamItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { TextView self = (TextView) v; Sample ds = (Sample) self.getTag(); Intent myIntent = new Intent(); myIntent.putExtra("link_info", ds.Sample); setResult("link_clicked", myIntent); finish(); } }); txtSamItem.measure(0, 0); widthSoFar += txtSamItem.getMeasuredWidth(); if (widthSoFar >= maxWidth) { ll.addView(llAlso); llAlso = new LinearLayout(this); llAlso.setLayoutParams(new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); llAlso.setOrientation(LinearLayout.HORIZONTAL); llAlso.addView(txtSamItem); widthSoFar = txtSamItem.getMeasuredWidth(); } else { llAlso.addView(txtSamItem); } } ll.addView(llAlso); } } 

截至2016年5月,谷歌已经创build了自己的stream量箱布局,其function类似于上面提到的库。

你可以在这里findGitHub仓库: https : //github.com/google/flexbox-layout

老问题,但如果有人在这里结束,两个图书馆做到这一点:

https://github.com/blazsolar/FlowLayout

https://github.com/ApmeM/android-flowlayout

寻找类似但更简单的问题的解决scheme,即以水平布局包装子文本内容。 kape123的解决scheme工作正常。 但是,使用ClickableSpanfind一个更简单的问题。 也许这对一些简单的情况可能是有用的。 片段:

  String[] stringSource = new String[sourceList.size()]; for (int i = 0; c < sourceList.size(); i++) { String text = sourceList.get(i); stringSource[i] = text; } SpannableString totalContent = new SpannableString(TextUtils.join(",", stringSource)); int start = 0; for (int j = 0; j < stringSource.length(); j++) { final String text = stringSource[j]; ClickableSpan span = new ClickableSpan() { @Override public void updateDrawState(TextPaint ds) { ds.setUnderlineText(true); ds.setColor(getResources().getColor(R.color.green)); } @Override public void onClick(View widget) { // the text clicked } }; int end = (start += text.length()); totalContent.setSpan(span, start, end, 0); star = end + 1; } TextView wrapperView = (TextView) findViewById(horizontal_container_id); wrapperView.setMovementMethod(LinkMovementMethod.getInstance()); wrapperView.setText(totalContent, BufferType.SPANNABLE); } 
 //this method will add image view to liner grid and warp it if no space in new child LinearLayout grid private void addImageToLinyerLayout(LinearLayout ll , ImageView v) { //set the padding and margin and weight v.setPadding(5, 5, 5, 5); Display display = getWindowManager().getDefaultDisplay(); int maxWidth = display.getWidth() - 10; int maxChildeNum = (int) ( maxWidth / (110)) ; Toast.makeText(getBaseContext(), "c" + v.getWidth() , Toast.LENGTH_LONG).show(); //loop through all child of the LinearLayout for (int i = 0; i < ll.getChildCount(); i++) { View chidv = ll.getChildAt(i); Class c = chidv.getClass(); if (c == LinearLayout.class) { //here we are in the child lay out check to add the imageView if there is space //Available else we will add it to new linear layout LinearLayout chidvL = (LinearLayout)chidv; if(chidvL.getChildCount() < maxChildeNum) { chidvL.addView(v); return; } } else{ continue; } } //if you reached here this means there was no roam for adding view so we will //add new linear layout LinearLayout childLinyer = new LinearLayout(this); childLinyer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); childLinyer.setOrientation(LinearLayout.HORIZONTAL); ll.addView(childLinyer); childLinyer.addView(v); } 

上面的方法将像agrid和你的布局并排添加imgeview

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/imageslayout" ></LinearLayout> 

我发布这个解决scheme可能会帮助一些人,并保存一些时间,我用它在我的应用程序

我结束了使用一个TagView :

 <com.cunoraz.tagview.TagView android:id="@+id/tag_group" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" /> TagView tagGroup = (TagView)findviewById(R.id.tag_view); //You can add one tag tagGroup.addTag(Tag tag); //You can add multiple tag via ArrayList tagGroup.addTags(ArrayList<Tag> tags); //Via string array addTags(String[] tags); //set click listener tagGroup.setOnTagClickListener(new OnTagClickListener() { @Override public void onTagClick(Tag tag, int position) { } }); //set delete listener tagGroup.setOnTagDeleteListener(new OnTagDeleteListener() { @Override public void onTagDeleted(final TagView view, final Tag tag, final int position) { } }); 

在这里输入图像描述