2017-06-06 10 views
9

में सापेक्ष लयआउट के समतुल्य क्या एंड्रॉइड पर रिलेवेटलाइट के समान कुछ लागू करने का कोई तरीका है?Flutter

विशेष रूप से मैं centerInParent को कुछ इसी तरह की तलाश में हूँ, layout_below :, layout_above :, और alignParentLeft

RelativeLayout के बारे में अधिक जानकारी के लिए: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

संपादित करें: यहाँ पर भरोसा एक लेआउट का एक उदाहरण है Screenshot

RelativeLayout तो में छवि के ऊपर, शीर्ष पर, "टोफू के गीत" पाठ centerInParent के रूप में एक रिश्तेदार लेआउट के अंदर गठबंधन है। जबकि अन्य 2 संरेखित हैं पेरेंट लिफ्ट और alignParentRight

प्रत्येक सेल पर, जहां आग आइकन है, इसके नीचे की पसंद की संख्या ज्वाला आइकन के केंद्र के चारों ओर गठबंधन है। साथ ही, प्रत्येक सेल पर शीर्ष और निचला शीर्षक क्रमशः छवि अवतार के दाईं ओर और नीचे से गठबंधन किया जाता है।

उत्तर

33

फ़्लटर लेआउट आमतौर पर Column, Row और Stack विजेट के पेड़ का उपयोग करके बनाया जाता है। ये विजेट कन्स्ट्रक्टर तर्क लेते हैं जो बच्चों को माता-पिता के सापेक्ष कैसे रखे जाते हैं, इसके नियमों को निर्दिष्ट करते हैं, और आप Expanded, Flexible, Positioned, Align, या Center विजेट्स में उन्हें लपेटकर अलग-अलग बच्चों के लेआउट को भी प्रभावित कर सकते हैं।

CustomMultiChildLayout का उपयोग कर जटिल लेआउट बनाना भी संभव है। इस प्रकार Scaffold आंतरिक रूप से कार्यान्वित किया गया है, और एक ऐप में इसका उपयोग करने का एक उदाहरण Shrine demo में दिखाई देता है। आप LayoutBuilder या CustomPaint का उपयोग भी कर सकते हैं, या में दिखाए गए अनुसार RenderObject का विस्तार कर सकते हैं। अपने लेआउट मैन्युअल रूप से ऐसा करना अधिक काम है और कोने के मामलों में त्रुटियों के लिए अधिक संभावित बनाता है, इसलिए यदि आप कर सकते हैं तो मैं उच्च स्तरीय लेआउट प्राइमेटिव्स के साथ प्राप्त करने का प्रयास करूंगा।

अपने विशिष्ट सवालों के जवाब देने के लिए:

  • अपने अनुप्रयोग बार तत्वों स्थिति AppBar को leading और trailing तर्क का प्रयोग करें। यदि आप इसके बजाय का उपयोग करना चाहते हैं, तो mainAxisAlignmentMainAxisAlignment.spaceBetween का उपयोग करें।
  • RowcrossAxisAlignmentCrossAxisAlignment.center के साथ आग आइकन और संख्या को नीचे रखने के लिएका उपयोग करें।
  • mainAxisAlignmentMainAxisAlignment.spaceBetween के साथ अपने शीर्ष और निचले शीर्षक की स्थिति के लिए उपयोग करें। (आप सूची टाइल्स बाहर रखना ListTile उपयोग करने पर विचार करना चाहिए, लेकिन आप सटीक स्थिति पर नियंत्रण खो देंगे यदि आप ऐसा करते।)

कोड स्निपेट है कि डिजाइन आपके द्वारा दी गई लागू करता है। इस उदाहरण में मैंने गीत टाइल्स की ऊंचाई निर्धारित करने के लिए IntrinsicHeight का उपयोग किया था, लेकिन आप उन्हें निश्चित ऊंचाई पर हार्ड कोडिंग करके प्रदर्शन में सुधार कर सकते हैं।

screenshot

import 'package:flutter/material.dart'; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     title: 'Flutter Demo', 
     theme: new ThemeData(
     brightness: Brightness.dark, 
     primaryColorBrightness: Brightness.dark, 
    ), 
     home: new HomeScreen(), 
     debugShowCheckedModeBanner: false, 
    ); 
    } 
} 

class Song extends StatelessWidget { 
    const Song({ this.title, this.author, this.likes }); 

    final String title; 
    final String author; 
    final int likes; 

    @override 
    Widget build(BuildContext context) { 
    TextTheme textTheme = Theme 
     .of(context) 
     .textTheme; 
    return new Container(
     margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), 
     padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), 
     decoration: new BoxDecoration(
     color: Colors.grey.shade200.withOpacity(0.3), 
     borderRadius: new BorderRadius.circular(5.0), 
    ), 
     child: new IntrinsicHeight(
     child: new Row(
      crossAxisAlignment: CrossAxisAlignment.stretch, 
      children: <Widget>[ 
      new Container(
       margin: const EdgeInsets.only(top: 4.0, bottom: 4.0, right: 10.0), 
       child: new CircleAvatar(
       backgroundImage: new NetworkImage(
        'http://thecatapi.com/api/images/get?format=src' 
        '&size=small&type=jpg#${title.hashCode}' 
       ), 
       radius: 20.0, 
      ), 
      ), 
      new Expanded(
       child: new Container(
       child: new Column(
        crossAxisAlignment: CrossAxisAlignment.start, 
        mainAxisAlignment: MainAxisAlignment.spaceBetween, 
        children: <Widget>[ 
        new Text(title, style: textTheme.subhead), 
        new Text(author, style: textTheme.caption), 
        ], 
       ), 
      ), 
      ), 
      new Container(
       margin: new EdgeInsets.symmetric(horizontal: 5.0), 
       child: new InkWell(
       child: new Icon(Icons.play_arrow, size: 40.0), 
       onTap:() { 
        // TODO(implement) 
       }, 
      ), 
      ), 
      new Container(
       margin: new EdgeInsets.symmetric(horizontal: 5.0), 
       child: new InkWell(
       child: new Column(
        mainAxisAlignment: MainAxisAlignment.center, 
        crossAxisAlignment: CrossAxisAlignment.center, 
        children: <Widget>[ 
        new Icon(Icons.favorite, size: 25.0), 
        new Text('${likes ?? ''}'), 
        ], 
       ), 
       onTap:() { 
        // TODO(implement) 
       }, 
      ), 
      ), 
      ], 
     ), 
    ), 
    ); 
    } 
} 

class Feed extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new ListView(
     children: [ 
     new Song(title: 'Trapadelic lobo', author: 'lillobobeats', likes: 4), 
     new Song(title: 'Different', author: 'younglowkey', likes: 23), 
     new Song(title: 'Future', author: 'younglowkey', likes: 2), 
     new Song(title: 'ASAP', author: 'tha_producer808', likes: 13), 
     new Song(title: '', author: 'TraphousePeyton'), 
     new Song(title: 'Something sweet...', author: '6ryan'), 
     new Song(title: 'Sharpie', author: 'Fergie_6'), 
     ], 
    ); 
    } 
} 

class CustomTabBar extends AnimatedWidget implements PreferredSizeWidget { 
    CustomTabBar({ this.pageController, this.pageNames }) 
    : super(listenable: pageController); 

    final PageController pageController; 
    final List<String> pageNames; 

    @override 
    final Size preferredSize = new Size(0.0, 40.0); 

    @override 
    Widget build(BuildContext context) { 
    TextTheme textTheme = Theme 
     .of(context) 
     .textTheme; 
    return new Container(
     height: 40.0, 
     margin: const EdgeInsets.all(10.0), 
     padding: const EdgeInsets.symmetric(horizontal: 20.0), 
     decoration: new BoxDecoration(
     color: Colors.grey.shade800.withOpacity(0.5), 
     borderRadius: new BorderRadius.circular(20.0), 
    ), 
     child: new Row(
     mainAxisAlignment: MainAxisAlignment.spaceBetween, 
     children: new List.generate(pageNames.length, (int index) { 
      return new InkWell(
      child: new Text(
       pageNames[index], 
       style: textTheme.subhead.copyWith(
       color: Colors.white.withOpacity(
        index == pageController.page ? 1.0 : 0.2, 
       ), 
      ) 
      ), 
      onTap:() { 
       pageController.animateToPage(
       index, 
       curve: Curves.easeOut, 
       duration: const Duration(milliseconds: 300), 
      ); 
      } 
     ); 
     }) 
      .toList(), 
    ), 
    ); 
    } 
} 

class HomeScreen extends StatefulWidget { 
    @override 
    _HomeScreenState createState() => new _HomeScreenState(); 
} 

class _HomeScreenState extends State<HomeScreen> { 

    PageController _pageController = new PageController(initialPage: 2); 

    @override 
    build(BuildContext context) { 
    final Map<String, Widget> pages = <String, Widget>{ 
     'My Music': new Center(
     child: new Text('My Music not implemented'), 
    ), 
     'Shared': new Center(
     child: new Text('Shared not implemented'), 
    ), 
     'Feed': new Feed(), 
    }; 
    TextTheme textTheme = Theme 
     .of(context) 
     .textTheme; 
    return new Stack(
     children: [ 
     new Container(
      decoration: new BoxDecoration(
      gradient: new LinearGradient(
       begin: FractionalOffset.topCenter, 
       end: FractionalOffset.bottomCenter, 
       colors: [ 
       const Color.fromARGB(255, 253, 72, 72), 
       const Color.fromARGB(255, 87, 97, 249), 
       ], 
       stops: [0.0, 1.0], 
      ) 
     ), 
      child: new Align(
      alignment: FractionalOffset.bottomCenter, 
      child: new Container(
       padding: const EdgeInsets.all(10.0), 
       child: new Text(
       'T I Z E', 
       style: textTheme.headline.copyWith(
        color: Colors.grey.shade800.withOpacity(0.8), 
        fontWeight: FontWeight.bold, 
       ), 
      ), 
      ) 
     ) 
     ), 
     new Scaffold(
      backgroundColor: const Color(0x00000000), 
      appBar: new AppBar(
      backgroundColor: const Color(0x00000000), 
      elevation: 0.0, 
      leading: new Center(
       child: new ClipOval(
       child: new Image.network(
        'http://i.imgur.com/TtNPTe0.jpg', 
       ), 
      ), 
      ), 
      actions: [ 
       new IconButton(
       icon: new Icon(Icons.add), 
       onPressed:() { 
        // TODO: implement 
       }, 
      ), 
      ], 
      title: const Text('tofu\'s songs'), 
      bottom: new CustomTabBar(
       pageController: _pageController, 
       pageNames: pages.keys.toList(), 
      ), 
     ), 
      body: new PageView(
      controller: _pageController, 
      children: pages.values.toList(), 
     ), 
     ), 
     ], 
    ); 
    } 
} 

अंतिम नोट: इस उदाहरण में, मैं एक नियमित AppBar इस्तेमाल किया है, लेकिन आप भी पिन किए गए SliverAppBar 0.0 का एक elevation है कि के साथ एक CustomScrollView इस्तेमाल कर सकते हैं। इससे सामग्री को दृश्यमान बना दिया जाएगा क्योंकि यह आपके ऐप बार के पीछे स्क्रॉल करता है। यह PageView के साथ अच्छी तरह से खेलने के लिए मुश्किल है, क्योंकि यह एक निश्चित आकार क्षेत्र को स्वयं को बाहर रखने की उम्मीद कर रहा है।

+0

उत्तर के लिए धन्यवाद कॉलिन! मैंने एक स्क्रीनशॉट का एक उदाहरण पोस्ट किया जहां मैं रिलेवेटिवआउट – user3217522

+0

वाह का उपयोग कर रहा हूं, इस तरह के विस्तृत उत्तर के लिए वाह बहुत बहुत धन्यवाद !!! – user3217522

+4

मेरी इच्छा है कि मैं इसे एक से अधिक बार वोट दे सकता हूं। –