Esmaeil Ahmadipour
Esmaeil Ahmadipour

Reputation: 1172

how to create new text widget for flutter package?

I need to create a custom text-widget in the Flutter. I have to change any color it accepts in the style with an opacity of 0.7. If it does not have a style, I have to show the color from the default style with an opacity of 0.7 .

My problem is creating a new text widget with the feature I described.

Upvotes: 1

Views: 888

Answers (4)

Divyang Rana
Divyang Rana

Reputation: 31

Custom Text using Getx

class CustomText extends StatelessWidget {
  final String text;
  final FontWeight fontWeight;
  final double fontSize;
  final Color color;
  final TextDirection textDirection;
  final TextAlign textAlign;
  final bool softWrap;
  final FontStyle fontStyle;

  CustomText({
    Key? key,
    required this.text,
    this.fontWeight = FontWeight.normal,
    this.fontSize = 14.0,
    this.color = Colors.black,
    this.textDirection = TextDirection.ltr,
    this.textAlign = TextAlign.left,
    this.softWrap = true,
    this.fontStyle = FontStyle.italic,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(
        fontWeight: fontWeight,
        fontSize: fontSize,
        color: color,
        fontStyle: fontStyle,
      ),
      textDirection: textDirection,
      textAlign: textAlign,
      softWrap: softWrap,
    );
  }
}

Using like this:

appBar: CustomAppBar(title: CustomText(text: "Home"),)

Upvotes: 0

Esmaeil Ahmadipour
Esmaeil Ahmadipour

Reputation: 1172

I could have used the widget Opacity very easily, but due to the Flutter document for Opacity Widget (resource) and the high cost of re-rendering the child, it was not necessary. The whole problem could be solved by DefaultTextStyle. You only need to pay attention to handling the context, which is documented in the code below.

Two modes are seen in the following code:

1- If TextStyle is not defined for your Text widget, it follows the default color at DefaultTextStyle.of.(context) or Theme and then manual Opacity value is also set.

2- If TextStyle is defined for your Text widget, it follows the defined color and its manual Opacity value is also set.

import 'package:flutter/material.dart';

const double OPACITY_VALUE = 0.7;

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomeWidget(),
    );
  }
}

class HomeWidget extends StatelessWidget {
  const HomeWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    /// ATTENTION: parent of this context is Material App  .
    return Scaffold(
      body: Center(
        child: Builder(builder: (context2) {
          /// context2 is important because referred to parent , and parent is Scaffold .
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              /// color and textStyle of this text widget referred to current Theme or DefaultTextStyle .
              Text(
                'You have pushed the button this many times:',
                style: DefaultTextStyle.of(context2).style.copyWith(
                    color: DefaultTextStyle.of(context2)
                        .style
                        .color!
                        .withOpacity(OPACITY_VALUE)),
              ),
              const CustomizedTextWidget(color: Colors.purple),
            ],
          );
        }),
      ),
    );
  }
}

class CustomizedTextWidget extends StatelessWidget {
  const CustomizedTextWidget({
    Key? key,
    required this.color,
  }) : super(key: key);
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Text(
      '0',
      style: TextStyle(color: color, fontSize: 32)
          .copyWith(color: color.withOpacity(OPACITY_VALUE)),
    );
  }
}

Upvotes: 0

mondayrris
mondayrris

Reputation: 724

The working solution simply uses

  • ThemeData.primaryColor for the configuration of default text color;
  • If it does not have a TextStyle passes to CustomTextWidget, the default text color is used with an opacity of 0.7;
  • If it does have a TextStyle passes to CustomTextWidget, the textStyle is used with an opacity of 0.7.

Codes here:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: const HomeWidget(title: _title),
      theme: ThemeData.light().copyWith(
        // default text color
        primaryColor: Colors.pink,
        colorScheme: ColorScheme.fromSwatch().copyWith(
          // change the appbar color
          primary: Colors.green[800],
        ),
      ),
    );
  }
}

class HomeWidget extends StatelessWidget {
  const HomeWidget({
    Key? key,
    required String title,
  })  : _title = title,
        super(key: key);

  final String _title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_title),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: const [
          CustomTextWidget(text: 'text does not have a style'),
          CustomTextWidget(
            text: 'text with passed black color style and fontSize 24',
            textStyle: TextStyle(
              fontSize: 24,
              color: Colors.black
            ),
          ),
          CustomTextWidget(
            text: 'text with passed blue color style',
            textStyle: TextStyle(
                color: Colors.blue
            ),
          ),
        ],
      ),
    );
  }
}

class CustomTextWidget extends StatelessWidget {
  final String text;
  final TextStyle? textStyle;

  const CustomTextWidget({Key? key, required this.text, this.textStyle}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final TextStyle finalTextStyle = textStyle ?? const TextStyle();
    final Color? finalColor = textStyle != null && textStyle!.color != null
        ? textStyle!.color
        : Theme.of(context).primaryColor;

    return Text(
      text,
      // it accepts in the style with an opacity of 0.7.
      style: finalTextStyle.copyWith(color: finalColor!.withOpacity(0.7)),
    );
  }
}

Expected outcome:

enter image description here

Upvotes: 0

Prashant
Prashant

Reputation: 676

There are multiple ways to approach this problem:

You can make a function based Widget or a class based Widget:

Function based Widget:

Widget myCustomText({required String data, Color? customColor}) {
    return Opacity(
      opacity: 0.7,
      child: Text(
        data,
        style: TextStyle(
          color: customColor ?? Colors.black,
        ),
      ),
    );
  }

Another approach is making a class based widget:

class MyCustomText extends StatelessWidget {
  final String data;
  final Color? customColor;
  const MyCustomText({Key? key, required this.data, this.customColor})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Opacity(
      opacity: 0.7,
      child: Text(
        data,
        style: TextStyle(color: customColor ?? Colors.black),
      ),
    );
  }
}

Here's how you can implement your custom text wherever required: // Code M:

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [

          //Widget based Implementation
          myCustomTextWidget(data: "Hello world"),
          myCustomTextWidget(data: "Hello Peter", customColor: Colors.amber),

          //Class based implementation
          MyCustomTextClassWidget(data: "Hello Spidey"),
          MyCustomTextClassWidget(data: "Hello 007", customColor: Colors.orange,)
        ],
      ),
    );
  }
}

Explanation: Null(??) operator checks if whether the value is given or not and if not given, then it will used default value after it.

Conclusion: Using Class based Widget i.e. Approach Number 2 is more robust and using class based widget is recommended by Flutter Official Team. It is also rebuild freindly and highly performant.

Output of the above code(M): Output of Code M

Upvotes: 4

Related Questions