Easy Way Responsive Design Development in Flutter With VelocityX and ScreenUtil

ozgunergen
KoçSistem
Published in
6 min readNov 17, 2022

Today, I will talk about responsive design development with flutter. Firstly we need two SDK for that VelocityX and Flutter_ScreenUtil. These two SDK make our job easier.

Why We Use Flutter_ScreenUtil

We are using for adapting screen and font size with this SDK.

Example Usage

    ScreenUtil().setWidth(540)  (dart sdk>=2.6 : 540.w) //Adapted to screen width
ScreenUtil().setHeight(200) (dart sdk>=2.6 : 200.h) //Adapted to screen height , under normal circumstances, the height still uses x.w
ScreenUtil().radius(200) (dart sdk>=2.6 : 200.r) //Adapt according to the smaller of width or height
ScreenUtil().setSp(24) (dart sdk>=2.6 : 24.sp) //Adapter font
12.sm //return min(12,12.sp)

ScreenUtil().pixelRatio //Device pixel density
ScreenUtil().screenWidth (dart sdk>=2.6 : 1.sw) //Device width
ScreenUtil().screenHeight (dart sdk>=2.6 : 1.sh) //Device height
ScreenUtil().bottomBarHeight //Bottom safe zone distance, suitable for buttons with full screen
ScreenUtil().statusBarHeight //Status bar height , Notch will be higher
ScreenUtil().textScaleFactor //System font scaling factor

ScreenUtil().scaleWidth //The ratio of actual width to UI design
ScreenUtil().scaleHeight //The ratio of actual height to UI design

ScreenUtil().orientation //Screen orientation
0.2.sw //0.2 times the screen width
0.5.sh //50% of screen height
20.setVerticalSpacing // SizedBox(height: 20 * scaleHeight)
20.horizontalSpace // SizedBox(height: 20 * scaleWidth)
const RPadding.all(8) // Padding.all(8.r) - take advantage of const key word
EdgeInsets.all(10).w //EdgeInsets.all(10.w)
REdgeInsets.all(8) // EdgeInsets.all(8.r)
EdgeInsets.only(left:8,right:8).r // EdgeInsets.only(left:8.r,right:8.r).
BoxConstraints(maxWidth: 100, minHeight: 100).w //BoxConstraints(maxWidth: 100.w, minHeight: 100.w)
Radius.circular(16).w //Radius.circular(16.w)
BorderRadius.all(Radius.circular(16)).w

Mostly we will use it to set the width and height value on the screens as a percentage. (0.2.sw = 20 percent width, 0.5.sh = 50 percent hight )

Why We Use VelocityX

With this library, you can develop user interfaces in a fast, easy and fun way. There are 9 main topics in Velocity_x. İf you are an iOS developer, you will be very easy for you to adapt to this library.

  • Customization
  • Layout (Mostly used)
  • Typography
  • Shapes
  • Responsive
  • SuperVx
  • Extension
  • StateManagement
  • Navigator

Mostly I used Layout, Colors, Typography and same Extensions. Today I will tell you this titles.

I am not using this SDK for State Management and Navigator. I think GetX is the best for that.

Colors

VelocityX includes a generous palette of great-looking, well-balanced colors that are perfect for prototyping or for kicking off a brand new project.

Example Usage, you can find more color usage this url


Vx.yellow
Vx.hexToColor("#FAFAFA");
Vx.blue900
Color myColor = Vx.randomColor;
Color myColor = Vx.randomPrimaryColor;
Color myColor = Vx.randomOpaqueColor;

Layout — Padding

.p0() padding: 0px; 
.p1() padding: 1px;
.p2() padding: 2px;
.p4() padding: 4px;
.p8() padding: 8px;
.p12() padding: 12px;
.p16() padding: 16px;
.p20() padding: 20px;
.p24() padding: 24px;
.p32() padding: 32px;
.p64() padding: 64px;

Text().p(10) // It will give 10px paddings from all directions.
Text().pLTRB(1,2,3,4) // It will give 1px left, 2px top, 3px right, 4px bottom paddings.
Text().pOnly(left:8,top:16) //It will give 8px left and 16px top paddings.

Layout — Flex

Mostly I have been used this part for developing user interface.

Velocity_X Flex
VStack(this.children, // should not be null
{Key key,
this.alignment = MainAxisAlignment.start,
this.crossAlignment = CrossAxisAlignment.start,
this.axisSize = MainAxisSize.min})
----------------------------------------------------------
VStack(
[
Text("VelocityX is Super"),
Text("Sample Text"),
Text("Yet, Another Sample Text"),
],
).scrollVertical().p20();


const HStack(this.children, // should not be null
{Key key,
this.alignment = MainAxisAlignment.start,
this.crossAlignment = CrossAxisAlignment.center,
this.axisSize = MainAxisSize.min})
----------------------------------------------------------
HStack(
[
Text("VelocityX is Super").px12(),
Text("Sample Text").px12(),
Text("Yet, Another Sample Text").px12(),
],
).scrollHorizontal().p20();

---------------------------------------------------------
const ZStack(this.children, // should not be null
{Key key,
this.alignment = AlignmentDirectional.topStart,
this.fit = StackFit.loose,
this.overflow = Overflow.clip})

ZStack(
[
VxBox().blue500.height(110.0).width(110.0).make(),
VxBox().green500.height(90.0).width(90.0).make(),
VxBox().red500.height(70.0).width(70.0).make(),
],
alignment: Alignment.center,
).p20();

We will design a sample screen soon using them.

Layout-Box

Velocity_X Box
VxBox({this.child})
VxBox(child: Text("Hello").centered())
.height(100)
.width(100)
.red500
.make()
.centered();

Layout — Scroll
VxScrollVorizontal is a widget that can be used to create horizontal scroll behaviour in the application.

const VxScrollVertical({
Key key,
this.controller,
this.physics,
this.padding,
this.child,
}) : super(key: key)
----------------------------------------------------
VxScrollHorizontal(
physics: AlwaysScrollableScrollPhysics(),
child: <Widget>[
'First Text'.text.make(),
'Second Text'.text.make()
].hStack(),
);
----------------------------------------------------
[
'First Text'.text.make(),
'Second Text'.text.make()
].hStack().scrollHorizontal()

There are many functions in the library that support us. I couldn’t explain all of them. You can find more details on this page. Let’s design a sample interface.

Page 1

Firstly we will create 4 function for the UI.

  • leftSideWidget(),
  • navigationBarWidget()
  • MainWidget()
  • bottomBarWidget()

For Left Side Widget

I didn’t care about the use of themes to show the usage of the library. I used Vx.hexToColor()

  Widget leftSideWidget(BuildContext context) {
return VxBox(
child: VStack(
[
Text(
"Code \nGeneration",
style: TextStyle(
fontSize: 16.sp,
color: Vx.hexToColor("#4561D6"),
),
).paddingOnly(left: 23, top: 28, right: 23, bottom: 28),
Text(
"Version 1.0.0",
style: TextStyle(
fontSize: 12,
fontFamily: "Poppins",
color: Vx.hexToColor("#939393"),
),
).paddingOnly(left: 23, top: 0, right: 23, bottom: 0),
const Image(
image: AssetImage('assets/left_center_image.png'),
).paddingOnly(left: 13, top: 56, right: 13, bottom: 0),
],
),
).width(0.3.sw).height(1.0.sh).make().box.hexColor("#F2F2F2").make();
}

The Width value is 30 percent of the screen, the Height value is 100 percent of the screen.

For Top Navigation Bar widget

Widget topNavigationWidget(BuildContext context) {
var selectedCircleColor = Vx.hexToColor("#E0E2FD");
var unSelectedCircleColor = const Color.fromRGBO(0, 0, 0, 0);
var selectedTextColor = Vx.hexToColor("#3B61C0");
var unSelectedTextcolor = Vx.hexToColor("#A0A0A0 ");
return HStack([
Text(
"1",
style: TextStyle(
color: logic.selectedPage.value == 1
? selectedTextColor
: unSelectedTextcolor),
).centered().circle(
backgroundColor: logic.selectedPage.value == 1
? selectedCircleColor
: unSelectedCircleColor,
radius: 35),
Text("2",
style: TextStyle(
color: logic.selectedPage.value == 2
? selectedTextColor
: unSelectedTextcolor))
.centered()
.circle(
backgroundColor: logic.selectedPage.value == 2
? selectedCircleColor
: unSelectedCircleColor,
radius: 35),
Text("3",
style: TextStyle(
color: logic.selectedPage.value == 3
? selectedTextColor
: unSelectedTextcolor))
.centered()
.circle(
backgroundColor: logic.selectedPage.value == 3
? selectedCircleColor
: unSelectedCircleColor,
radius: 35),
], alignment: MainAxisAlignment.spaceAround)
.paddingOnly(left: 0.2.sw, right: 0.2.sw)
.w(1.0.sw)
.h(64)
.box
.make();
}

For Bottom Bar Widget

HStack bottomBarWidgetForFirstPage() {
return HStack([
Spacer(),
TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
backgroundColor: MaterialStateProperty.all<Color>(
Vx.hexToColor("#4561D6"),),
),
onPressed: () {
logic.selectedPage.value = 2;
},
child: HStack([
Spacer(),
Text('NEXT'),
Spacer(),
Icon(Icons.arrow_forward).paddingOnly(right: 10)
]),
).w(190).h(60).paddingOnly(top: 15, right: 20)
]);
}

For Main Page Widget

Widget mainPageWidget() {
return HStack([
VStack([
HStack([
Image(image: AssetImage("assets/unselected_icon.png")).w(20).h(20),
const Text("Localization-Swift",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
height: 1.0))
.p(20),
]).onTap(() {
//Do Something
}).box.make(),

HStack([
Image(image: AssetImage("assets/selected_icon.png")).w(20).h(20),
const Text("Networking-Swift",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
height: 1.0))
.p(20),
]).onTap(() {
//Do Something
}).box.make()

]).w(0.3.sw),
VStack([]).w(0.3.sw)
]).centered();
}

For Body widget

We combine all our codes in this function and we have completed our visual interface.

HStack bodyWidget(BuildContext context) {
return HStack([
leftSideWidget(context),
VStack([
topNavigationWidget(context),

//For Line
VxBox().width(0.7.sw).height(2).hexColor("#545355").make(),

//Message
const Text("Lorem Ipsum",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white))
.p(20),
const Text(
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: Vx.hexToColor("#939393")))
.paddingOnly(left: 20, right: 20),

//For Main Widget, if you want to show other view by workflow,
// only you must set widget this line
VxBox(child: mainPageWidget()).width(0.7.sw).height(0.6.sh).make(),

VxBox().width(0.7.sw).height(2).hexColor("#545355").make(),// For Line

bottomButtonWidgetForFirstPage()

]).w(0.7.sw).h(1.0.sh).box.hexColor("#333235").make(),
]);
}
Result

Thank you for reading my article.

Referance Link

--

--