如何在 NativeScript 中的绝对布局底部定位元素?

Posted

技术标签:

【中文标题】如何在 NativeScript 中的绝对布局底部定位元素?【英文标题】:How to position element at the bottom of Absolute Layout in NativeScript? 【发布时间】:2017-12-24 09:07:34 【问题描述】:

我想在 NativeScript 中的绝对布局中将一个元素定位在屏幕底部。

我有这个代码:

<AbsoluteLayout>
    <maps:mapView 
        left="0"
        top="0"
        
        
        latitude=" map.latitude " 
        longitude=" map.longitude " 
        zoom=" map.zoom "
        padding=" map.padding "  
        mapReady="onMapReady"
        coordinateTapped="onCoordinateTapped"
        markerSelect="onMarkerSelect"
        shapeSelect="onShapeSelect"
        cameraChanged="onMapCameraChanged"/>

    <ScrollView
        left="0"
        top="0"
        
        orientation="horizontal">
        <!-- More XML -->
    </ScrollView>

    <StackLayout
        left="0"
        bottom="0"
        
        visibility="visible"
        orientation="horizontal"
        style="background-color: red;">

        <Label text="TITLE"></Label>

    </StackLayout>
</AbsoluteLayout>

我发现AbsoluteLayout没有底部属性...这是我要创建的图片:

那么如何排列图片中的物品,尤其是底部的物品?

编辑:我应该注意这个底部矩形的尺寸可能并不总是相同的......

【问题讨论】:

【参考方案1】:

GridLayout也可以做到:

<GridLayout rows="16,*,16" columns="16,*,16"  backgroundColor="red">
    <GridLayout row="1" col="1" rows="auto, auto, auto" columns="auto" horizontalAlignment="right" verticalAlignment="bottom" backgroundColor="blue">
        <!-- Your content at bottom right corner -->
        <Label row="0" text="Your content" textAlignment="center" textWrap="true"></Label>
        <Label row="1" text="at" textAlignment="center" textWrap="true"></Label>
        <Label row="2" text="bottom right corner" textAlignment="center"></Label>
    </GridLayout>
</GridLayout>

【讨论】:

【参考方案2】:

这是绝对最佳的解决方案,从其中一位开发者处获得:https://github.com/NativeScript/NativeScript/issues/5591#issuecomment-482640921

<GridLayout rows="*,auto">
   <ItemTakingFullScreen rowSpan="2"/>
   <ItemShownUnder row="1"/>
   <ItemShownAbove row="1">
</GridLayout>

基本上,您可以使用网格布局,让一个项目占据多个网格空间,并与其他项目共享。

【讨论】:

【参考方案3】:

这是最好的解决方案 将所有元素包装在一个绝对布局中,宽度和高度为 100%,并可能添加一个网格布局来保存主要内容。

        <AbsoluteLayout width='100%' height='100%'>
           <StackLayout width='100%' hieght='100%' left='0' top='0'>
                 //add you structure here

           </StackLayout>
           add your fixed element here

           <image src='add the float item'/>
       </AbsoluteLayout>

【讨论】:

【参考方案4】:

另一种选择是在您的 AbsoluteLayout 容器中使用 FlexboxLayout,如下所示:

<FlexboxLayout flexDirection="column" justifyContent="space-between" >
    <ScrollView
        
        orientation="horizontal">
        <!-- More XML -->
    </ScrollView>

    <StackLayout
        
        visibility="visible"
        orientation="horizontal"
        style="background-color: red;">

        <Label text="TITLE"></Label>

    </StackLayout>
</FlexboxLayout>

【讨论】:

【参考方案5】:

有一天我做了类似的事情,以编程方式 & 使用 Angular,也许这会有所帮助。

如果您不想使用 GridLayout,您可以尝试获取底部元素和屏幕的高度,然后通过简单的计算从顶部放置元素:屏幕的高度 - 底部元素的高度(如果你想要一些填充)。您可以使用两种类型的值:DIP 和像素。如果您使用像素,则需要使用屏幕比例将值转换为 DIP。

类似这样的(我没有测试我给你的代码,这只是一个例子)

1] 为你的底部元素添加一个 id,这样你就可以在你的组件中访问它:

<StackLayout #bottomElt></StackLayout>

2] 更新您的组件以在绝对布局中设置元素位置

// you need ElementRef, OnInit and ViewChild
import  Component, ElementRef, OnInit, ViewChild, ViewContainerRef  from "@angular/core";
import  AbsoluteLayout  from "ui/layouts/absolute-layout";
import  StackLayout  from "ui/layouts/stack-layout";
// you need access to screen properties
import  screen  from "tns-core-modules/platform";
[...]

export class YourComponent implements OnInit 
    // add access to element inside your component
    @ViewChild("bottomElt") bottomElt: ElementRef;

    // create variable to access bottom element properties
    bottomContainer: StackLayout;

    // set bottom element position after view init
    // example : inside ngOnInit function (for Angular version)
    ngOnInit(): void 
        this.bottomContainer = <StackLayout>this.bottomElt.nativeElement;

        // using DIPs values only
        AbsoluteLayout.setTop(this.bottomContainer, (screen.mainScreen.heightDIPs - Number(this.bottomContainer.height)));

        // using pixels and screen scale
        // this way you can get height without knowing it
        AbsoluteLayout.setTop(this.bottomContainer, (screen.mainScreen.heightDIPs - (Number(this.bottomContainer.getMeasuredHeight()) / screen.mainScreen.scale)));

    

有关屏幕值的更多信息:https://docs.nativescript.org/api-reference/interfaces/platform.screenmetrics.html

另一种方式

您可以使用 GridLayout 来设置底部栏,而不是使用 AbsoluteLayout,它有两行:一排具有通配符大小,另一排具有自动大小,以便每次更改时都能适应底部栏的高度。我在移动应用程序中这样做是为了在 androidios 的底部获得一个菜单:

<GridLayout rows="*, auto" >
    <AbsoluteLayout row="0" orientation="vertical">
        <!-- YOUR CONTENT (maps & ScrollView) -->
    </AbsoluteLayout>

    <!-- YOUR BOTTOM BAR (StackLayout). Don't forget to add row="1" -->
    <StackLayout #bottomElt row="1">[...]</StackLayout>
</GridLayout>

【讨论】:

你知道我怎样才能计算底栏的高度,因为它里面的内容会随着时间的推移而改变,而且它也会被显示/隐藏。所以我需要在显示它之前计算它的新高度......或者即使它被隐藏它也会在内容更改后更新它的高度而我不计算它? 您可以使用getMeasuredHeight() 函数并将其转换为DIP,然后在每次更改他的内容时更改他的位置。您也可以采用完全不同的方式:使用 GridLayout 显示底部栏,您可以使用 visibility 属性隐藏/显示该栏。这样,无论他的身高如何,您的底栏都将始终位于底部,并且主要内容将始终填满所有可用空间。我将在我的答案中添加此选项 我选择了第一个解决方案。因此,布局最初是隐藏的,标签是空的。在未来的某个时候,一个事件被触发,它应该用适当的文本显示这个隐藏的布局。所以我写bottomBarLabel.text='some text'; let h = bottomBar.getMeasuredHeight();。但是 bottomBar 的高度为零,至少 getMeasuredHeight() 返回零。但是我设置了一个超时来运行,并在该超时打印出 getMeasuredHeight() 并且它是正确的,但我不喜欢使用超时函数来等待组件计算它的高度.... 不错的解决方案。在 Angular 中,我会将计算移至“ngAfterViewInit()”,以避免在 Angular 完成绘制之前尝试访问元素时出错。

以上是关于如何在 NativeScript 中的绝对布局底部定位元素?的主要内容,如果未能解决你的问题,请参考以下文章

css如何将导航绝对定位到页面底部

NativeScript BottomNavigation -> 如何在底部导航项点击时打开默认页面?

css的绝对布局问题,怎么让子元素置于底部?

如何在 NativeScript 布局中查找/查看视图的尺寸?

NativeScript:如果用户点击 RadListView 中的空白空间,我如何捕捉点击事件?

如何在 nativescript 中进行水平轮播布局?