如何在AbsoluteLayout上强制使用方形布局?

时间:2017-10-12 16:25:59

标签: xamarin xamarin.forms

任何人都知道为什么下面的代码不能在我的Forms应用程序中执行OnMeasure()?我基本上试图强制AbsoluteLayout具有相同的高度/宽度以显示为正方形:

public class AbsoluteSquareLayout : AbsoluteLayout
{
    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
    {
        var size = Math.Min(widthConstraint, heightConstraint);
        return base.OnMeasure(size, size);
    }
}

1 个答案:

答案 0 :(得分:3)

Layout调用中覆盖大小限制并不能保证最终大小 - 因为来自父布局的最终​​AbsoluteLayout传递将覆盖此值。 XF文章here详细讨论了这一点。

为了能够实现正方形布局 - 您必须更新父布局以考虑这些约束,并确保它在布局传递中传递。

例如,您可以扩展SquareLayout.IsSquare以动态计算子项的大小限制。默认情况下,此自定义布局将所有子项视为正方形。为了覆盖特定孩子的行为,您可以将附加属性false设置为public class SquareLayout : AbsoluteLayout { public static readonly BindableProperty IsSquareProperty = BindableProperty.CreateAttached("IsSquare", typeof(bool), typeof(SquareLayout), defaultValue: true, defaultBindingMode: BindingMode.OneWay); public static bool GetIsSquare(BindableObject view) { return (bool)view.GetValue(IsSquareProperty); } public static void SetIsSquare(BindableObject view, bool value) { view.SetValue(IsSquareProperty, value); } Dictionary<View, Rectangle> _boundsCache = new Dictionary<View, Rectangle>(); protected override void LayoutChildren(double x, double y, double width, double height) { foreach(var child in Children) { var isSquare = GetIsSquare(child); if(isSquare) { Rectangle bounds; if (!_boundsCache.ContainsKey(child)) _boundsCache[child] = bounds = GetLayoutBounds(child); else bounds = _boundsCache[child]; var absFlags = GetLayoutFlags(child); var widthIsProportional = (absFlags & AbsoluteLayoutFlags.WidthProportional) != 0; var heightIsProportional = (absFlags & AbsoluteLayoutFlags.HeightProportional) != 0; var childWidth = widthIsProportional ? bounds.Width * width : bounds.Width; var childHeight = heightIsProportional ? bounds.Height * height : bounds.Height; var size = Math.Min(childWidth, childHeight); SetLayoutBounds( child, new Rectangle( bounds.X, bounds.Y, (widthIsProportional ? (size / width) : size), (heightIsProportional ? (size / height) : size) ) ); } } base.LayoutChildren(x, y, width, height); } }

<local:SquareLayout>
    <AbsoluteLayout BackgroundColor="Green" 
                    AbsoluteLayout.LayoutBounds=".1,.1,1,1" 
                    AbsoluteLayout.LayoutFlags="All" />

    <AbsoluteLayout BackgroundColor="Blue" 
                    AbsoluteLayout.LayoutBounds=".5,.5,.2,.1" 
                    AbsoluteLayout.LayoutFlags="All" />

    <AbsoluteLayout BackgroundColor="Red" 
                    AbsoluteLayout.LayoutBounds=".9,.9,200,200" 
                    AbsoluteLayout.LayoutFlags="PositionProportional" />

    <AbsoluteLayout BackgroundColor="Yellow" 
                    AbsoluteLayout.LayoutBounds="10,20,.3,.3" 
                    AbsoluteLayout.LayoutFlags="SizeProportional" />

    <AbsoluteLayout BackgroundColor="Silver" 
                    local:SquareLayout.IsSquare="false"
                    AbsoluteLayout.LayoutBounds=".9,.9,1,.1" 
                    AbsoluteLayout.LayoutFlags="All" />
</local:SquareLayout>

样本使用:

    function onOpen() { // This function adds a custom menu to the spreadsheet (Backup to archive) so you can run the script from there.


var ui = SpreadsheetApp.getUi();
    ui.createMenu('Backup')
    .addItem('Backup','dataBackup')
    .addItem('Name','nameOfSpreadsheet')
    .addToUi();

 }
 function nameOfSpreadsheet() {
var s=SpreadsheetApp.getActive().getName().replace(/(\d{1,2}\.\d{1,2}\.\d{1,2}).*/,'$1');
return s;
}

  function dataBackup() {
  var inputSS = SpreadsheetApp.getActiveSpreadsheet();
  var archiveSS = SpreadsheetApp.openById('146WU8RghfFqlCpCSX7n6kBAKOyxcpVKt14yhVfvYz-g');
  var user = Session.getActiveUser().getEmail();
  var sheetNames = ['AM trip', 'PM trip', 'Pool / Beach', 'Night Dive'];
  for (var i = 0; i < sheetNames.length; i++) {

    var inputSheet = inputSS.getSheetByName(sheetNames[i]);
    var archiveSheet = archiveSS.getSheetByName(sheetNames[i]);

    var date = inputSheet.getRange('A2').getValue(); // Changed to stop inadvertent cell changes, also made text white so not seen.
    var data = inputSheet.getRange('E7:U37').getValues().filter(function(row) { return row[0] !== '' || row[1] !== ''});

    for (var x = 0; x < data.length; x++) {
        data[x].splice(0, 0, date);
    }
    var getDate = archiveSheet.getRange(archiveSheet.getLastRow(), 1).getValue();
    var maxRowLength = data.reduce(function(length, row) { return Math.max(length, row.length); }, 0);
    var date = new Date(date); 

    if (date.getDate() === "Loading Data...") {
    Utilities.sleep(10000);
    SpreadsheetApp.flush();

    if (getDate.getDate() != date.getDate() || getDate.getMonth() != date.getMonth()) {     

        if (data.length != 0) {
            archiveSheet.insertRowsAfter(archiveSheet.getLastRow(), data.length);
            archiveSheet.getRange(archiveSheet.getLastRow() + 1, 1, data.length, maxRowLength).setValues(data);
        } else {
            archiveSheet.insertRowsAfter(archiveSheet.getLastRow(), 1);
            archiveSheet.getRange(archiveSheet.getLastRow() + 1, 1, 1, 2).setValues([[date, 'No Data']]);
       }}}}}

enter image description here enter image description here