我有这样的代码:
<TableSection>
<ViewCell Height="200">
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
<Button Text="ABCDEFG"></Button>
</ViewCell>
</TableSection>
我想做的是让按钮看起来像标签云,并扩展ViewCell高度以适应它们。
我没有看到任何关于如何做到这一点的例子,并希望得到一些反馈/建议。
由于
更新1 - 以下是我尝试但不起作用
<ViewCell Height="200">
<StackLayout Orientation="Horizontal" IsClippedToBounds="false" Spacing="5">
<Button Text="ABCDEF1" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF2" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF3" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF4" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF5" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF6" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF7" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
<Button Text="ABCDEF8" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
</Button>
</StackLayout>
</ViewCell>
不幸的是,我看到的只是前四个按钮,之后没有任何内容。我希望看到的是第一行上的按钮,然后是第二行上的另外四个按钮,其中视图单元的高度扩展到适合。
答案 0 :(得分:3)
正如迭戈建议的那样,我们可以自定义Layout
来实现期望风格。
创建源自Layout<View>
的新子类,我们只需要
覆盖OnMeasure
以返回此布局的大小。
覆盖LayoutChildren
以确定孩子的位置和大小。
创建Bindable Properties
以个性化每次需要的使用。
public class WrapLayout : Layout<View>
{
public static readonly BindableProperty SpacingProperty =
BindableProperty.Create
(
"Spacing",
typeof(double),
typeof(WrapLayout),
10.0,
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).OnSizeChanged()
);
public double Spacing
{
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
private void OnSizeChanged()
{
this.ForceLayout();
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
if (WidthRequest > 0)
widthConstraint = Math.Min(widthConstraint, WidthRequest);
if (HeightRequest > 0)
heightConstraint = Math.Min(heightConstraint, HeightRequest);
double internalWidth = double.IsPositiveInfinity(widthConstraint) ? double.PositiveInfinity : Math.Max(0, widthConstraint);
double internalHeight = double.IsPositiveInfinity(heightConstraint) ? double.PositiveInfinity : Math.Max(0, heightConstraint);
return DoHorizontalMeasure(internalWidth, internalHeight);
}
private SizeRequest DoHorizontalMeasure(double widthConstraint, double heightConstraint)
{
int rowCount = 1;
double width = 0;
double height = 0;
double minWidth = 0;
double minHeight = 0;
double widthUsed = 0;
foreach (var item in Children)
{
var size = item.Measure(widthConstraint, heightConstraint);
height = Math.Max(height, size.Request.Height);
var newWidth = width + size.Request.Width + Spacing;
if (newWidth > widthConstraint)
{
rowCount++;
widthUsed = Math.Max(width, widthUsed);
width = size.Request.Width;
}
else
width = newWidth;
minHeight = Math.Max(minHeight, size.Minimum.Height);
minWidth = Math.Max(minWidth, size.Minimum.Width);
}
if (rowCount > 1)
{
width = Math.Max(width, widthUsed);
height = (height + Spacing) * rowCount - Spacing; // via MitchMilam
}
return new SizeRequest(new Size(width, height), new Size(minWidth, minHeight));
}
protected override void LayoutChildren(double x, double y, double width, double height)
{
double rowHeight = 0;
double yPos = y, xPos = x;
foreach (var child in Children.Where(c => c.IsVisible))
{
var request = child.Measure(width, height);
double childWidth = request.Request.Width;
double childHeight = request.Request.Height;
rowHeight = Math.Max(rowHeight, childHeight);
if (xPos + childWidth > width)
{
xPos = x;
yPos += rowHeight + Spacing;
rowHeight = 0;
}
var region = new Rectangle(xPos, yPos, childWidth, childHeight);
LayoutChildIntoBoundingRegion(child, region);
xPos += region.Width + Spacing;
}
}
}
<local:WrapLayout Spacing="5">
<Button Text="111111111111111" BackgroundColor="Red"/>
<Button Text="222" BackgroundColor="Green"/>
<Button Text="33333333333333333333333333" BackgroundColor="Gray"/>
<Button Text="444444" BackgroundColor="Blue"/>
<Button Text="5" BackgroundColor="Orange"/>
<Button Text="6666666666666666" BackgroundColor="Aqua"/>
<Button Text="77777777" BackgroundColor="Yellow"/>
<Button Text="888" BackgroundColor="Pink"/>
<Button Text="9 9 9 9" BackgroundColor="Purple"/>
<Button Text="10" BackgroundColor="Brown"/>
</local:WrapLayout>
答案 1 :(得分:2)
您可以按照xamarin表单开发人员网站https://developer.xamarin.com/guides/xamarin-forms/user-interface/layouts/custom/
提供的指南来实现此目的您描述的问题与本指南所示的示例代码完全相同。创建自定义布局,您可以在任何需要的地方重用此解决方案。
简洁地说,您需要做的就是创建WrapLayout:
答案 2 :(得分:1)
why not use a StackLayout ?
package org.stackoverflow.jena.customaggregate;
import com.google.common.base.Joiner;
import org.apache.jena.atlas.logging.LogCtl;
import org.apache.jena.graph.Graph;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprEvalException;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.expr.aggregate.Accumulator;
import org.apache.jena.sparql.expr.aggregate.AccumulatorFactory;
import org.apache.jena.sparql.expr.aggregate.AggCustom;
import org.apache.jena.sparql.expr.aggregate.AggregateRegistry;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.graph.NodeConst;
import org.apache.jena.sparql.sse.SSE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AggGroupConcatSorted {
static {
LogCtl.setCmdLogging();
}
static AccumulatorFactory accumulatorFactory = (agg, distinct) -> new AccGroupConcatSorted(agg);
static class AccGroupConcatSorted implements Accumulator {
private AggCustom agg;
private List<String> nodeStrList = new ArrayList<>();
AccGroupConcatSorted(AggCustom agg) {
this.agg = agg;
}
@Override
public void accumulate(Binding binding, FunctionEnv functionEnv) {
ExprList exprList = agg.getExprList();
for (Expr expr : exprList) {
try {
NodeValue nv = expr.eval(binding, functionEnv);
// Evaluation succeeded, add string to list
nodeStrList.add(nv.asString());
} catch (ExprEvalException ex) {
}
}
}
@Override
public NodeValue getValue() {
// sort list
Collections.sort(nodeStrList);
// return single node which in fact is the concatenated string of the list elements
return NodeValue.makeString(Joiner.on(" ").join(nodeStrList));
}
}
public static void main(String[] args) {
// Example aggregate that concatenates the node values in sorted order
String aggUri = "http://example.org/group_concat_sorted" ;
// register the custom aggregate - returns unbound for no rows
AggregateRegistry.register(aggUri, accumulatorFactory, NodeConst.nodeMinusOne);
// sample data
Graph g = SSE.parseGraph("(graph (:s :p \"b\") (:s :p \"bc\") (:s :p \"abc\"))") ;
String qs = "SELECT (<http://example.org/group_concat_sorted>(?o) AS ?x) {?s ?p ?o}" ;
// query execution
Query q = QueryFactory.create(qs) ;
try ( QueryExecution qexec = QueryExecutionFactory.create(q, ModelFactory.createModelForGraph(g)) ) {
ResultSet rs = qexec.execSelect() ;
ResultSetFormatter.out(rs);
}
}
}