D1APP-24 home page (static)
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
|
@ -60,9 +60,28 @@ class DesignConfig {
|
|||
static const BorderRadius lowBorderRadius = BorderRadius.all(
|
||||
Radius.circular(8),
|
||||
);
|
||||
static const BorderRadius mediumBorderRadius = BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
);
|
||||
static const BorderRadius highBorderRadius = BorderRadius.all(
|
||||
Radius.circular(16),
|
||||
);
|
||||
static final Border lightBorder = Border.all(color: DesignConfig.greyColor4);
|
||||
static final BoxDecoration actionCardDecoration = BoxDecoration(
|
||||
color: lightPrimaryColor3,
|
||||
boxShadow: defaultShadow,
|
||||
borderRadius: mediumBorderRadius,
|
||||
);
|
||||
static final List<BoxShadow> defaultShadow = [
|
||||
BoxShadow(
|
||||
color: const Color(0XFF4D4D4D).withOpacity(0.25),
|
||||
offset: const Offset(0, 4),
|
||||
blurRadius: 8,
|
||||
spreadRadius: 0,
|
||||
)
|
||||
];
|
||||
|
||||
static const Duration defaultAppDuration = Duration(milliseconds: 400);
|
||||
static const Duration defaultAnimationDuration = Duration(milliseconds: 600);
|
||||
|
||||
static final SystemUiOverlayStyle systemUIOverlayStyle = SystemUiOverlayStyle(
|
||||
statusBarBrightness: Brightness.dark,
|
||||
|
|
|
|||
|
|
@ -4,10 +4,21 @@ class Assets {
|
|||
static const String _baseAnimationsPath = _basePath + '/animations';
|
||||
|
||||
static const String verticalLogoWithText =
|
||||
_baseImagesPath + '/logo/logo-v-t.png';
|
||||
_baseImagesPath + '/logos/logo-v-t.png';
|
||||
static const String horizontalLogoWithText =
|
||||
_baseImagesPath + '/logo/logo-h-t.png';
|
||||
_baseImagesPath + '/logos/logo-h-t.png';
|
||||
|
||||
static const String logoLoadingAnimation =
|
||||
_baseAnimationsPath + '/indicator.riv';
|
||||
|
||||
static const businessCategoryIcon =
|
||||
_baseImagesPath + '/categories/business.png';
|
||||
static const economicCategoryIcon =
|
||||
_baseImagesPath + '/categories/economic.png';
|
||||
static const enviromentalCategoryIcon =
|
||||
_baseImagesPath + '/categories/enviromental.png';
|
||||
static const politicalCategoryIcon =
|
||||
_baseImagesPath + '/categories/political.png';
|
||||
static const socialCategoryIcon = _baseImagesPath + '/categories/social.png';
|
||||
static const techCategoryIcon = _baseImagesPath + '/categories/tech.png';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
class RadarCategory {
|
||||
final int id;
|
||||
final String title;
|
||||
final String asset;
|
||||
|
||||
RadarCategory({required this.id, required this.title, required this.asset});
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ class _AuthenticationState extends State<Authentication> {
|
|||
return Scaffold(
|
||||
body: Consumer<AuthenticationState>(
|
||||
builder: (context, state, child) => AnimatedSwitcher(
|
||||
duration: DesignConfig.defaultAppDuration,
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
child: _pages[state.currentPageIndex],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/pages/home/widgets/categories_gird.dart';
|
||||
import 'package:didvan/pages/home/widgets/categories_list.dart';
|
||||
import 'package:didvan/pages/home/widgets/search_field.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:didvan/widgets/logos/didvan_vertical_logo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
const Home({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
bool _isColapsed = false;
|
||||
bool _isAnimating = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_scrollController.addListener(() async {
|
||||
if (_isAnimating) return;
|
||||
final double position = _scrollController.position.pixels;
|
||||
if (position > 5 && !_isColapsed) {
|
||||
_isColapsed = true;
|
||||
setState(() {});
|
||||
_isAnimating = true;
|
||||
await _scrollController.animateTo(
|
||||
380,
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
curve: Curves.ease,
|
||||
);
|
||||
_isAnimating = false;
|
||||
} else if (position < 380 && _isColapsed) {
|
||||
_isColapsed = false;
|
||||
setState(() {});
|
||||
_isAnimating = true;
|
||||
await _scrollController.animateTo(
|
||||
0,
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
curve: Curves.ease,
|
||||
);
|
||||
_isAnimating = false;
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final d = MediaQuery.of(context);
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
CustomScrollView(
|
||||
controller: _scrollController,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.all(
|
||||
20,
|
||||
).copyWith(top: d.padding.top + 20),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Container(
|
||||
alignment: Alignment.centerRight,
|
||||
height: 76,
|
||||
child: const DidvanHorizontalLogo(),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SliverPadding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: SearchField(),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(top: 300, right: 16, bottom: 20),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: DidvanText(
|
||||
'آخرین رصد',
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
color: DesignConfig.darkPrimaryColor2,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
CategoriesRow1(isColapsed: _isColapsed),
|
||||
CategoriesRow2(isColapsed: _isColapsed),
|
||||
CategoriesList(isColapsed: _isColapsed),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:didvan/models/radar_category.dart';
|
||||
import 'package:didvan/providers/core_provider.dart';
|
||||
|
||||
class HomeState extends CoreProvier {
|
||||
final List<RadarCategory> categories = [
|
||||
RadarCategory(
|
||||
id: 1,
|
||||
title: 'افتصادی',
|
||||
asset: Assets.economicCategoryIcon,
|
||||
),
|
||||
RadarCategory(
|
||||
id: 2,
|
||||
title: 'سیاسی',
|
||||
asset: Assets.politicalCategoryIcon,
|
||||
),
|
||||
RadarCategory(
|
||||
id: 3,
|
||||
title: 'فناوری',
|
||||
asset: Assets.techCategoryIcon,
|
||||
),
|
||||
RadarCategory(
|
||||
id: 4,
|
||||
title: 'کسب و کار',
|
||||
asset: Assets.businessCategoryIcon,
|
||||
),
|
||||
RadarCategory(
|
||||
id: 5,
|
||||
title: 'زیست محیطی',
|
||||
asset: Assets.enviromentalCategoryIcon,
|
||||
),
|
||||
RadarCategory(
|
||||
id: 6,
|
||||
title: 'اجتماعی',
|
||||
asset: Assets.socialCategoryIcon,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/pages/home/home_state.dart';
|
||||
import 'package:didvan/pages/home/widgets/category_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CategoriesRow1 extends StatelessWidget {
|
||||
final bool isColapsed;
|
||||
const CategoriesRow1({Key? key, required this.isColapsed}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final MediaQueryData d = MediaQuery.of(context);
|
||||
return AnimatedPositioned(
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
top: isColapsed ? 12 : 176 + d.padding.top,
|
||||
left: isColapsed ? -d.size.width : 0,
|
||||
right: isColapsed ? d.size.width : 0,
|
||||
child: Row(
|
||||
children: context
|
||||
.read<HomeState>()
|
||||
.categories
|
||||
.sublist(0, 3)
|
||||
.map(
|
||||
(category) => Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
child: CategoryItem(
|
||||
title: category.title,
|
||||
asset: category.asset,
|
||||
isColapsed: isColapsed,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CategoriesRow2 extends StatelessWidget {
|
||||
const CategoriesRow2({
|
||||
Key? key,
|
||||
required this.isColapsed,
|
||||
}) : super(key: key);
|
||||
|
||||
final bool isColapsed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final MediaQueryData d = MediaQuery.of(context);
|
||||
return AnimatedPositioned(
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
top: isColapsed ? -60 : 300 + d.padding.top,
|
||||
left: isColapsed ? -80 : 0,
|
||||
right: isColapsed ? 124 : 0,
|
||||
child: Row(
|
||||
children: context
|
||||
.read<HomeState>()
|
||||
.categories
|
||||
.sublist(3, 6)
|
||||
.map(
|
||||
(category) => Expanded(
|
||||
child: CategoryItem(
|
||||
title: category.title,
|
||||
asset: category.asset,
|
||||
isColapsed: isColapsed,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/models/radar_category.dart';
|
||||
import 'package:didvan/pages/home/home_state.dart';
|
||||
import 'package:didvan/widgets/animated_visibility.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CategoriesList extends StatelessWidget {
|
||||
final bool isColapsed;
|
||||
const CategoriesList({Key? key, required this.isColapsed}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final MediaQueryData d = MediaQuery.of(context);
|
||||
final HomeState state = context.read<HomeState>();
|
||||
final List<RadarCategory> categories = [];
|
||||
categories.addAll(state.categories.sublist(3, 6));
|
||||
categories.addAll(state.categories.sublist(0, 3));
|
||||
return Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: AnimatedCrossFade(
|
||||
crossFadeState:
|
||||
isColapsed ? CrossFadeState.showSecond : CrossFadeState.showFirst,
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
firstChild: const SizedBox(),
|
||||
secondChild: Container(
|
||||
height: 60 + d.padding.top,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
boxShadow: DesignConfig.defaultShadow,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: EdgeInsets.only(
|
||||
top: d.padding.top + 12,
|
||||
bottom: 12,
|
||||
right: 12,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
AnimatedVisibility(
|
||||
isVisible: isColapsed,
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
child: _itemBuilder(
|
||||
RadarCategory(title: 'همه', asset: '', id: 0),
|
||||
),
|
||||
),
|
||||
for (var category in categories) _itemBuilder(category),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _itemBuilder(RadarCategory category) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
width: 100,
|
||||
padding: const EdgeInsets.all(4),
|
||||
alignment: Alignment.center,
|
||||
child: DidvanText(category.title),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: DesignConfig.darkPrimaryColor2,
|
||||
),
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/widgets/animated_visibility.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CategoryItem extends StatelessWidget {
|
||||
final String title;
|
||||
final String asset;
|
||||
final bool isColapsed;
|
||||
|
||||
const CategoryItem({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.asset,
|
||||
required this.isColapsed,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size ds = MediaQuery.of(context).size;
|
||||
return Center(
|
||||
child: AnimatedContainer(
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
padding: isColapsed ? const EdgeInsets.all(4) : EdgeInsets.zero,
|
||||
width: isColapsed ? 100 : ds.width / 3,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
border: isColapsed
|
||||
? Border.all(color: DesignConfig.darkPrimaryColor2)
|
||||
: null,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
AnimatedVisibility(
|
||||
duration: DesignConfig.defaultAnimationDuration,
|
||||
isVisible: !isColapsed,
|
||||
child: Container(
|
||||
width: ds.width / 5,
|
||||
height: ds.width / 5,
|
||||
decoration: DesignConfig.actionCardDecoration,
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Image.asset(
|
||||
asset,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
DidvanText(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.subtitle2,
|
||||
color: DesignConfig.darkPrimaryColor2,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SearchField extends StatelessWidget {
|
||||
const SearchField({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
DidvanIcons.search_regular,
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
textAlignVertical: TextAlignVertical.top,
|
||||
onChanged: (value) {},
|
||||
keyboardType: TextInputType.text,
|
||||
textInputAction: TextInputAction.search,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 12,
|
||||
right: 12,
|
||||
bottom: 8,
|
||||
),
|
||||
border: InputBorder.none,
|
||||
hintText: 'جستجو مطلب در رادار',
|
||||
hintStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle2!
|
||||
.copyWith(color: DesignConfig.greyColor5),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ class _SplashState extends State<Splash> {
|
|||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() => Navigator.of(context).pushReplacementNamed(
|
||||
Routes.authenticaion,
|
||||
Routes.home,
|
||||
),
|
||||
);
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:didvan/pages/authentication/authentication.dart';
|
||||
import 'package:didvan/pages/authentication/authentication_state.dart';
|
||||
import 'package:didvan/pages/home/home.dart';
|
||||
import 'package:didvan/pages/home/home_state.dart';
|
||||
import 'package:didvan/pages/splash/splash.dart';
|
||||
import 'package:didvan/pages/splash/splash_state.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
|
|
@ -11,18 +13,25 @@ class RouteGenerator {
|
|||
switch (settings.name) {
|
||||
case Routes.splash:
|
||||
return _materialPageRouteGenerator(
|
||||
ChangeNotifierProvider(
|
||||
ChangeNotifierProvider<SplashState>(
|
||||
create: (context) => SplashState(),
|
||||
child: const Splash(),
|
||||
),
|
||||
);
|
||||
case Routes.authenticaion:
|
||||
return _materialPageRouteGenerator(
|
||||
ChangeNotifierProvider(
|
||||
ChangeNotifierProvider<AuthenticationState>(
|
||||
create: (context) => AuthenticationState(),
|
||||
child: const Authentication(),
|
||||
),
|
||||
);
|
||||
case Routes.home:
|
||||
return _materialPageRouteGenerator(
|
||||
ChangeNotifierProvider<HomeState>(
|
||||
create: (context) => HomeState(),
|
||||
child: const Home(),
|
||||
),
|
||||
);
|
||||
default:
|
||||
return _errorRoute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
library animated_visibility;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum FadeMode {
|
||||
vertical,
|
||||
horizontal,
|
||||
both,
|
||||
}
|
||||
|
||||
class AnimatedVisibility extends StatefulWidget {
|
||||
final bool isVisible;
|
||||
final Duration duration;
|
||||
final Widget child;
|
||||
final Curve curve;
|
||||
final FadeMode fadeMode;
|
||||
|
||||
const AnimatedVisibility({
|
||||
Key? key,
|
||||
required this.isVisible,
|
||||
required this.duration,
|
||||
required this.child,
|
||||
this.fadeMode = FadeMode.both,
|
||||
this.curve = Curves.easeIn,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AnimatedVisibilityState createState() => _AnimatedVisibilityState();
|
||||
}
|
||||
|
||||
class _AnimatedVisibilityState extends State<AnimatedVisibility>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController _sizeController;
|
||||
late final Animation<double> _animation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_setupAnimation();
|
||||
_runSizeCheck();
|
||||
}
|
||||
|
||||
void _setupAnimation() {
|
||||
_sizeController =
|
||||
AnimationController(vsync: this, duration: widget.duration);
|
||||
_animation = CurvedAnimation(
|
||||
parent: _sizeController,
|
||||
curve: widget.curve,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AnimatedVisibility oldWidget) {
|
||||
_runSizeCheck();
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
void _runSizeCheck() {
|
||||
if (widget.isVisible) {
|
||||
_sizeController.forward();
|
||||
} else {
|
||||
_sizeController.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_sizeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get _isVertical =>
|
||||
widget.fadeMode == FadeMode.vertical || widget.fadeMode == FadeMode.both;
|
||||
bool get _isHorizontal =>
|
||||
widget.fadeMode == FadeMode.horizontal ||
|
||||
widget.fadeMode == FadeMode.both;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _animation,
|
||||
child: widget.child,
|
||||
builder: (context, child) => Align(
|
||||
heightFactor: _isVertical ? _animation.value : null,
|
||||
widthFactor: _isHorizontal ? _animation.value : null,
|
||||
child: Opacity(opacity: _animation.value, child: child),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ class DidvanText extends StatelessWidget {
|
|||
final Color? color;
|
||||
final FontWeight? fontWeight;
|
||||
final double? fontSize;
|
||||
final TextAlign textAlign;
|
||||
|
||||
const DidvanText(
|
||||
this.text, {
|
||||
|
|
@ -15,6 +16,7 @@ class DidvanText extends StatelessWidget {
|
|||
this.color,
|
||||
this.fontSize,
|
||||
this.fontWeight,
|
||||
this.textAlign = TextAlign.right,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -26,6 +28,7 @@ class DidvanText extends StatelessWidget {
|
|||
fontWeight: fontWeight,
|
||||
fontSize: fontSize,
|
||||
),
|
||||
textAlign: textAlign,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,5 +133,7 @@ class _DidvanTextFieldState extends State<DidvanTextField> {
|
|||
}
|
||||
}
|
||||
|
||||
String? _validator(String? value) {}
|
||||
String? _validator(String? value) {
|
||||
_hasError = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class InkWrapper extends StatelessWidget {
|
||||
final Color? splashColor;
|
||||
final Color? highlightColor;
|
||||
final Widget child;
|
||||
final VoidCallback? onPressed;
|
||||
final BorderRadius? borderRadius;
|
||||
|
||||
const InkWrapper({
|
||||
Key? key,
|
||||
this.splashColor,
|
||||
this.highlightColor,
|
||||
required this.child,
|
||||
this.onPressed,
|
||||
this.borderRadius,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
child,
|
||||
Positioned.fill(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: borderRadius,
|
||||
splashColor: splashColor,
|
||||
highlightColor: highlightColor,
|
||||
onTap: onPressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DidvanHorizontalLogo extends StatelessWidget {
|
||||
const DidvanHorizontalLogo({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Image.asset(Assets.horizontalLogoWithText);
|
||||
}
|
||||
}
|
||||
11
pubspec.yaml
|
|
@ -64,8 +64,15 @@ flutter:
|
|||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- lib/assets/images/logo/logo-v-t.png
|
||||
- lib/assets/images/logo/logo-h-t.png
|
||||
- lib/assets/images/logos/logo-v-t.png
|
||||
- lib/assets/images/logos/logo-h-t.png
|
||||
- lib/assets/images/categories/business.png
|
||||
- lib/assets/images/categories/economic.png
|
||||
- lib/assets/images/categories/enviromental.png
|
||||
- lib/assets/images/categories/political.png
|
||||
- lib/assets/images/categories/social.png
|
||||
- lib/assets/images/categories/tech.png
|
||||
- lib/assets/animations/indicator.riv
|
||||
- lib/assets/animations/indicator.riv
|
||||
|
||||
|
||||
|
|
|
|||