I use Stack widget for making overlay.
Let's imagine that.
1) I add PageView at the Bottom.
2) I add Container to make Gradient at the Top.
I WANT TO KNOW THAT
How can I scroll PageView in spite of Gradient is over it?
This is a example
body: Stack(
children: <Widget>[
PageView.builder(
itemBuilder: (BuildContext context, int index) => Container(
height: double.infinity,
width: double.infinity,
child: Text("Index: $index"),
color: _pageColors[index],
),
onPageChanged: (number) {
setState(() {
_pageFocus = number + 1;
});
print(number);
},
controller: _pageController,
itemCount: _pageColors != null ? _pageColors.length : 0,
),
Align(
alignment: AlignmentDirectional.bottomEnd,
child: Container(
height: 100.0,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(255, 255, 255, 0.0),
Colors.white,
],
stops: [
0.0,
3.0
],
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomCenter,
tileMode: TileMode.repeated),
),
width: double.infinity,
height: double.infinity,
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
alignment: AlignmentDirectional.centerStart,
child: Text('$_pageFocus/${_pageColors.length}')),
)
],
),
),
),
],
),
See if wrapping the Align in an IgonorePointer helps. docs.flutter.io/flutter/widgets/IgnorePointer-class.html
Related
I am trying to extend Stack a little bit down to create room for "All caught up" text.
Here is my code;
return Stack(
children: [
buildListView(scrollController),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
Widget buildBackToTop(ScrollController scrollController, bool backtoTop) {
if (backtoTop) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton.extended(
onPressed: () {
scrollController.animateTo(0,
duration: const Duration(milliseconds: 200),
curve: Curves.linear);
},
label: const Text("Back to Top"),
),
),
);
} else {
return const SizedBox();
}
}
Widget buildBottomReached(bool isLastIndex) {
if (isLastIndex) {
return const Align(
alignment: Alignment.bottomCenter,
child: Text(
"All caught up 🎉",
style: TextStyle(
color: Colors.blue, fontWeight: FontWeight.bold, fontSize: 20.00),
),
);
} else {
return const SizedBox();
}
}
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}
When I do following,
return Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30),
child: buildListView(scrollController),
),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
This is desired but it adds whitespace to bottom all the time,
Is there a way to do this?
another valid solution for your case is to expand the Stack to the screen size, then align your widgets with the Align widget like this:
final mq = MediaQuery.of(context);
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: mq.size.height,
minHeight: mq.size.height,
maxWidth: mq.size.width,
minWidth: mq.size.width,
),
child: Stack(
fit: StackFit.expand,
children: [
buildListView(scrollController),
Align(
alignment: Alignment.bottomCenter,
child: buildBackToTop(scrollController, backtoTop),
),
buildBottomReached(isLastIndex),
],
),
);
Based on your UI. try Column widget instead of Stack.
return Column(
children: [
Expaneded(child: buildListView(scrollController)),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
If it needs overlay, use Stack by combining listView and Text with Column.
Wrap the widget with Positioned and add bottom.
return Stack(
children: [
.....
Positioned(
bottom: yourValue,
child:
First, wrap Stack with ListView widget
Then, move buildBottomReached helper as a sibling of the Stack widget
return ListView(//this
children: [
Stack(
children: [
buildListView(),
buildBackToTop(backtoTop),
//buildBottomReached(isLastIndex),//move this a sibling of the Stack
],
),
buildBottomReached(isLastIndex),//moved here
],
);
Then, on buildListView helper, set ListView.builder property shrinkWrap to true.
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
shrinkWrap: true,//this
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}
i want a slidingUpPanel similar to YouTube comments section. that not open with the scrolling of the content but open and close only from the drag handle by tap or by swipe up/down).
the drag handle is the top section of the slidingUpPanel :
so the draggable should happen only from this drag handle not from the whole body. (you can try the code below to know what i mean)
it means if i scroll the body(the listView builder) the slidingUpPanel keep its place (either open or closed) until i swip it from the drag handle.
my current code:
PanelController panelController = PanelController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
SlidingUpPanel(
controller: panelController,
maxHeight: MediaQuery.of(context).size.height * .9,
minHeight: MediaQuery.of(context).size.height * .7,
borderRadius: BorderRadius.vertical(top: Radius.circular(40.0)),
panelBuilder: (controller) => Stack(
alignment: Alignment.topCenter,
children: [
GestureDetector(
onTap: () {
panelController.isPanelOpen
? panelController.close()
: panelController.open();
},
child: Container(
color: Colors.transparent,
height: 36.0,
width: MediaQuery.of(context).size.width,
child: Center(
child: Container(
width: 46.77,
height: 4.0,
decoration: BoxDecoration(color: Colors.grey),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
controller: controller,
padding: EdgeInsets.zero,
itemCount: 20,
itemBuilder: (context, index) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 70.0,
color: Colors.red,
),
),
],
);
}),
),
],
)),
],
),
));
}
Does anyone know how to round the video corners in a video call? The container that I place them in has a border radius, but when the video starts it always shows a square container.
My video render code is below:
#override
Widget build(BuildContext context) {
return Stack(
children: [
_localSwitchRender == true
? rtc_local_view.SurfaceView()
: rtc_remote_view.SurfaceView(uid: widget.remoteUid.first),
Align(
alignment: Alignment.topLeft,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: GestureDetector(
onTap: _switchRender,
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 42, 0, 0),
child: Stack(
children: [
Column(
children: [
const SizedBox(
height: 20
),
Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Color(0x66333333),
),
width: 158,
height: 220,
foregroundDecoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: _localSwitchRender
? rtc_remote_view.SurfaceView(
uid: widget.remoteUid.first,
renderMode: VideoRenderMode.FILL,
)
: rtc_local_view.SurfaceView(
renderMode: VideoRenderMode.Hidden,
zOrderMediaOverlay: true,
),
),
],
),
],
),
),
),
),
),
],
);
}
}
Any help is greatly appreciated!
Place your widget inside ClipRRect:
ClipRRect(
borderRadius: BorderRadius.circular(10)
child: // your widget
)
Thanks Xoltwan! That worked:
ClipRRect(
borderRadius: BorderRadius.circular(10)
child: // your widget
)
I am trying to make a animation show bookmark. Just like the example on this website.The orignial example is too complicated. So I put part of code from the example of flutter doc. To learn the easiest animation. I have put same tag in both hero,but still error.
Please help me out.Thanks!
Sorry my english is poor.
Center(
child: FutureBuilder(
future: fetchData('querySdiList'),
builder: (context, qS) {
if (qS.hasData) {
return CarouselSlider.builder(
itemCount: qS.data.length,
itemBuilder: (BuildContext context, int itemIndex, int i) {
final list = qS.data[itemIndex];
sdiId = list['sdiId'];
print('carousel:' + sdiId.toString());
return Center(
child: SizedBox(
width: 300,
child: Hero(
tag: sdiId.toString(),
child: Material(
child: InkWell(
onTap: () {
// Navigator.pushNamed(context, '/BookMarkPage');
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
print('Hero:' + sdiId.toString());
return Container(
// Set background to blue to emphasize that it's a new route.
color: Colors.lightBlueAccent,
padding: const EdgeInsets.all(16.0),
alignment: Alignment.topLeft,
child: SizedBox(
width: 100,
child: Hero(
tag: sdiId.toString(),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {},
child: Image.network(
_image[0],
fit: BoxFit.contain,
),
),
),
),
));
}));
},
child: Container(
height:
MediaQuery.of(context).size.height / 2,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 10,
)
],
),
margin: EdgeInsets.all(5.0),
child: Stack(
alignment: Alignment.bottomLeft,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: Container(
height: MediaQuery.of(context)
.size
.height /
2,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(_image[
Random().nextInt(
_image.length)])),
),
),
),
Container(
height: MediaQuery.of(context)
.size
.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(15)),
color: Colors.white,
gradient: LinearGradient(
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomLeft,
colors: [
Colors.transparent,
Colors.black,
],
stops: [0.0, .85],
),
),
),
Container(
padding: EdgeInsets.all(10),
child: RichText(
text: TextSpan(
text: '${list['sdiName']}',
style: TextStyle(
fontSize: 50,
color: Colors.white),
),
),
height: MediaQuery.of(context)
.size
.height /
8,
),
],
),
),
),
))));
},
options: CarouselOptions(
aspectRatio: 2,
autoPlay: true,
enlargeCenterPage: true,
height: MediaQuery.of(context).size.height,
),
);
} else if (qS.hasError) {
return qS.error;
}
return CircularProgressIndicator();
},
),
),
error
There are multiple heroes that share the same tag within a subtree.
You are creating multiple widgets with the carouselBuilder and each one of them is getting the same tag, you cant do that, the tag is what tells the Hero widget where it should animate to.
The problem seem to be here
final list = qS.data[itemIndex];
sdiId = list['sdiId'];
try setting the hero tag as something like this
tag: qS.data[itemIndex]['sdiId']
this should give each of the heros the sdiId of the itemIndex preventing them from having the same one
I do not know what is wrong with this image loading inside the slider , also I thought this has something to do with the debug but the release version has the same problem, overall all the pictures load slowly and have some delay but this problem is worse.
Container(
margin: EdgeInsets.only(top: Platform.isAndroid ? 85.0 : 115.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CarouselSlider(
aspectRatio: 1.1,
viewportFraction: 0.6,
initialPage: 0,
enlargeCenterPage: true,
reverse: false,
autoPlay: false,
enableInfiniteScroll: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index) {
if (!mounted) return;
setState(() {
_current = index;
SystemChrome.setEnabledSystemUIOverlays(
[SystemUiOverlay.bottom]);
});
},
items: [
slides("words", "assets/images/Academic_Words.jpg", "Academic\n Words", MyAppWords()),
slides("writing", "assets/images/writing.jpg", "Academic\n Writing", MyAppWriting()),
slides("conference", "assets/images/conference.jpg", "Academic\nConference", EnterPhone()),
slides("conversation", "assets/images/conversations.jpg", "Academic\nConversations", null),
slides("correspondence", "assets/images/correspondence.jpg", "Academic\nCorrespondence", MyAppCorrespondence()),
].map((imgUrl) {
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(
vertical: 20.0, horizontal: 9.0),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(48.0),
boxShadow: [
BoxShadow(
color:
Color.fromRGBO(50, 50, 50, 1),
blurRadius: 5.0,
// has the effect of softening the shadow
spreadRadius: 5.0,
// has the effect of extending the shadow
offset: Offset(
-1.0,
// horizontal, move right 10
8.0, //
// vertical, move down 10
),
)
]),
child: ClipRRect(
borderRadius: BorderRadius.circular(48.0),
child: imgUrl,
));
},
);
}).toList()),
]),
decoration: BoxDecoration(
borderRadius:
BorderRadius.vertical(top: Radius.circular(48.0)),
color: Color.fromRGBO(237, 237, 237, 1),
),
),
]);
},
));
}
slides(String _tag,String _asset, String _title, Widget myF ){
return GestureDetector(
child: Stack(
fit: StackFit.expand,
alignment: Alignment.center,
children: <Widget>[
Hero(
tag: _tag,
child: Image.asset(
_asset,
fit: BoxFit.cover,
),
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black45,
Colors.black54
],
begin: Alignment.topLeft,
end: Alignment.bottomRight
),
),
),
Container(
alignment: Alignment.center,
child: Text(
_title,
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.w400,
fontFamily: "Raleway"),
),
)
],
),
onTap: () => Navigator.push(context,
MaterialPageRoute(
builder: (BuildContext context) {
return myF;
})),
);
}
here is a demonstration of my problem=> http://uupload.ir/view/k2ub_video_2019-10-22_10-14-47.mp4/
The behavior seems to be caused by the scaling of the large image. Since carousel_slider: 2.0.0, it's recommended to pass CarouselOptions to options - wherein you can define either the height or aspect ratio for the carousel items.