I am making a login screen. I want to have the text: "By continuing you agree the xxx Terms & Conditions and Privacy Policy" where -terms and conditions- and -privacy policy- are buttons which when clicked on, navigate to two separate screens.
Is this possible in Flutter. Please take note that due to the length of the final text string, it could wrap onto more than one line depending on the screen size.
Really appreciate any help with this.
Carson
you can do it with RichText
Like this
class DoItWithRichText extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: RichText(
text: TextSpan(
text: "By continuing you agree the",
children:[
TextSpan(
text: " Terms and Conditions",
style: TextStyle(
color: Colors.blue
),
recognizer: TapGestureRecognizer()..onTap = () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => TermsAndConditions()))
),
TextSpan(
text: " and "
),
TextSpan(
text: "Privacy Policy",
style: TextStyle(
color: Colors.blue
),
recognizer: TapGestureRecognizer()..onTap = () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => PrivacyAndPolicy()))
)
],
style: TextStyle(
color: Colors.black,
fontSize: 13
)
),
),
),
),
);
}
}
You could use RawMaterialButton to do that:
class LongTextRowWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('By continuing you agree to the xxx '),
InlineTextButton(text: 'Terms and Conditions', function: _jumpToTermsAndConditions),
const Text(' and '),
InlineTextButton(text: 'Privacy Policy', function: _jumpToPrivacyPolicy),
],
);
}
}
class InlineTextButton extends StatelessWidget {
final String text;
final Function function;
InlineTextButton({this.text, this.function});
#override
Widget build(BuildContext context) {
return RawMaterialButton(
constraints: BoxConstraints(),
onPressed: function,
child: Text(
text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryColor,
),
),
);
}
}
Related
I'm using Provider in Flutter for state management. And I want to display some text in my widget using this Provider. The test is shown but is looks very strange height or padding I don't know. So here is a code.
class JobDetailsScreen extends HookWidget {
const JobDetailsScreen({required this.id, Key? key}) : super(key: key);
final String id;
#override
Widget build(BuildContext context) {
final job = Provider.of<JobsNotifier>(context).currentJob;
var loading = Provider.of<JobsNotifier>(context).isLoadingCurrentJob;
useEffect(() {
if (job == null) {
Future.microtask(() async {
await Provider.of<JobsNotifier>(context, listen: false)
.getCurrentJob(id);
});
}
return () => {};
}, [id]);
return Scaffold(
appBar: const NavBarTop(
title: 'Job Details',
innerAppBar: true,
),
body: loading
? const Center(
child: CircularProgressIndicator(),
)
: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(job.title,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 24)),
Text(job.company,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 18)),
ElevatedButton(
onPressed: () async {
try {
await openUrl(job.applyUrl!);
} on String catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
e,
style: const TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
));
}
},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(
const Size(double.infinity, 50))),
child: const Text('Apply'),
),
],
),
),
),
);
}
}
And I see this on my screen
Screen with wrong text behaviour
I'm expecting widget to show text the right way without any paading and some redundant height.
It should be like this:
Right text behaviour screen
The response might contain newlines. Like maybe job.title equals "\nUI/UI Design Lead\n\n".
Try use job.title.trim() so any leading and trailing whitespaces and newlines are removed.
i have tried to run your code, and it seems to work fine without any padding to the text widgets or height, heres's a screenshot:
i believe what you can do is to check through you NavBarTop widget, to see if there could be any property affecting this.
It shows this error although I have added late and required in the Question class constructor. It's repeatedly shows
Exception caught by widgets library
The following LateError was thrown building _BodyBuilder:
LateInitializationError: Field 'ques' has not been initialized
Main class:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'QuestionsAnswers.dart';
void main() {
runApp(const Quizzler());
}
class Quizzler extends StatelessWidget {
const Quizzler({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.grey[900],
leading: Icon(Icons.games),
title: Text(
'Quizzler',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
color: Colors.white,
),
),
),
body: QuizPlay(),
),
),
);
}
}
class QuizPlay extends StatefulWidget {
const QuizPlay({Key? key}) : super(key: key);
#override
State<QuizPlay> createState() => _QuizplayState();
}
class _QuizplayState extends State<QuizPlay> {
List<Icon> score=[];// array of score icon
List<Questions>questionsAndAnswers=[
Questions(a:'Pakistan is an under developed country',b:true),
Questions(a:'Imran Khan is the Prime Minister of Pakistan',b:true),
Questions(a:'Y comes after U',b:false)
];
int questiontracker=0;// variable to increment of questions
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
questionsAndAnswers[questiontracker].ques,
style: TextStyle(
fontSize: 25.0,
color: Colors.white70,
),
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green),
),
onPressed: () {
//Yes button
bool answer=questionsAndAnswers[questiontracker].ans;
if (answer==true)
{
print('correct answer');
}
else
{
print('wrong answer ');
}
setState(() {
questiontracker++;
score.add(Icon(Icons.check,color: Colors.green,)) ;
});
},
child: Text(
'Yes',
style: TextStyle(
fontSize: 20.0,
),
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: () {
// No button
bool answer=questionsAndAnswers[questiontracker].ans;
if (answer==false)
{
print('correct answer');
}
else
{
print('wrong answer ');
}
setState(() {
questiontracker++;
score.add(Icon(Icons.close,color: Colors.red,)) ;
});
},
child: Text(
'No',
style: TextStyle(
fontSize: 20.0,
),
),
),
),
),
Row(
children: score,
),
],
);
}
}
###Question CLASS###
class Questions{
late String ques;
late bool ans;
Questions({required String a,required bool b})
{
a=ques;
b=ans;
}
}
make it
ques = a;
ans = b;
This stores the value on the right in the value on the left.
Your class constructor Questions is wrong, change it to:
class Questions{
late String ques;
late bool ans;
Questions({required String a,required bool b}) {
ques = a;
and = b;
}
}
What is the purpose of having your questions as a plain class? I'd suggest turning it into a module class which in turn should be
class Question
{
String? ques;
bool? ans;
Question({
this.ques, this.ans});
}
and when you want to initialize a question I'd suggest creating a list
List<Question> questions = [];
question.add(Question("question",true));
// add more as you wish
This will allow you to turn it into JSON which will enable you to maybe provide questions from an online database to the app without needing to update the app every time you want to add a question.
code:
import 'package:flutter/material.dart';
class sonIslemlerUygulamasi extends StatelessWidget {
const sonIslemlerUygulamasi({Key? key}) : super(key: key);
get islemler => islemler;
#override
Widget build(BuildContext context) {
List <sonIslemler> islemler = [sonIslemler("10 Kasım", "Send money", "500 USD", "Borç"), sonIslemler("11 Kasım", "Withdraw money", "50 TL", "Yok")];
return Scaffold(
appBar: AppBar(
title: Text("Son işlemler"),
backgroundColor: Colors.red[500],
),
body: Center(
child: Column(
children: [
Text("\nSon işlemler", style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),),
Text("Son işlemler uygulamasına hoş geldiniz.\n", style: TextStyle(fontSize: 20), textAlign: TextAlign.center,),
Expanded(
child: ListView.builder(
itemCount: islemler.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
leading: processIcon(),
title: Text(islemler[index].islemTuru, style: TextStyle(fontSize: 20)),
subtitle: Text(islemler[index].islemTarihi,),
trailing: Text(islemler[index].islemMiktari, style: TextStyle(fontSize: 20)),
),
);
},
),
),
],
),
),
);
}
}
processIcon() {
// Process icon codes
}
class sonIslemler {
String islemTarihi;
String islemTuru;
String islemMiktari;
String islemAciklamasi;
sonIslemler(this.islemTarihi, this.islemTuru, this.islemMiktari, this.islemAciklamasi);
}
My goal is to make an application that displays recent financial transactions. I want to show different icon if money is sent, different icon if money is withdrawn, and separate icon for each transaction.
i will show the icons in leading.
Transactions are in the list of transactions.
How can I show different icon according to process?
import 'package:flutter/material.dart';
class sonIslemlerUygulamasi extends StatelessWidget {
const sonIslemlerUygulamasi({Key? key}) : super(key: key);
get islemler => islemler;
#override
Widget build(BuildContext context) {
List <sonIslemler> islemler = [sonIslemler("10 Kasım", "Send money", "500 USD", "Borç"), sonIslemler("11 Kasım", "Withdraw money", "50 TL", "Yok")];
return Scaffold(
appBar: AppBar(
title: Text("Son işlemler"),
backgroundColor: Colors.red[500],
),
body: Center(
child: Column(
children: [
Text("\nSon işlemler", style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),),
Text("Son işlemler uygulamasına hoş geldiniz.\n", style: TextStyle(fontSize: 20), textAlign: TextAlign.center,),
Expanded(
child: ListView.builder(
itemCount: islemler.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
leading: processIcon(transactionType),
title: Text(islemler[index].islemTuru, style: TextStyle(fontSize: 20)),
subtitle: Text(islemler[index].islemTarihi,),
trailing: Text(islemler[index].islemMiktari, style: TextStyle(fontSize: 20)),
),
);
},
),
),
],
),
),
);
}
}
Widget processIcon(String transactionType) {
switch transactionType{
case "sent":
return Icon(); // Put the icon for 'sent' here
case "withdrawn":
return Icon(); // Put the icon for 'withdrawn' here
case "transaction1":
return Icon(); // Put the icon for 'transaction1' here
case "transaction2":
return Icon(); // Put the icon for 'transaction2' here
default:
return Icon(); // Put a default icon in case transactionType variable is not one of the above.
}
}
class sonIslemler {
String islemTarihi;
String islemTuru;
String islemMiktari;
String islemAciklamasi;
sonIslemler(this.islemTarihi, this.islemTuru, this.islemMiktari, this.islemAciklamasi);
}
I am not sure what is type of your transaction. You should be able to pass it to the function and handle it from there.
Just check if money is sent or not and then return a different icon
if (isSent()){
return Icon(...)
}
else{
return Icon(...)
}
I'm trying to create a custom Alert dialogue using this package rflutter_alert . But when return the Alert it gives me this error
The argument type 'Future<bool?>' can't be assigned to the parameter type 'Widget?'.
Update:
here i created a custom widget of dialogue
class DialogueTwoButton extends StatelessWidget {
DialogueTwoButton(
{Key? key,
context,
required this.text1,
required this.text2,
required this.onpres1,
required this.onpress2})
: super(key: key);
final String text1;
final String text2;
final Function onpres1;
final Function onpress2;
#override
Widget build(BuildContext context) {
return _onAlertButtonsPressed(context, text1, text2, onpres1, onpress2);
}
var alertStyle = AlertStyle(
animationType: AnimationType.fromTop,
isCloseButton: false,
isOverlayTapDismiss: false,
descStyle: GoogleFonts.montserrat(color: Colors.black, fontSize: 18),
titleStyle: GoogleFonts.montserrat(
color: Colors.red,
),
);
_onAlertButtonsPressed(context, desc, title, onPressYes, onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
color: HexColor("#5344ed")),
DialogButton(
child: Text(
"No",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
and here is my other file where i'm creating a button
updateProduct() {
DialogueTwoButton(
onpres1: () {},
onpress2: () {},
text1: 'df',
text2: 'dsf',
);
bottomButton(context, () {
updateProduct();
}, "Update Product"),
and updateProduct(); on this mehtod calling the custom class dialogue, but it's not showing , i want to do this something in this way.
please help how to do this.
you missing one closing ) bracket after ).show()
_onAlertButtonsPressed(context,desc,title,onPressYes,onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
color: HexColor("#5344ed")),
DialogButton(
child: Text(
"No",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
Complete src code:
import 'package:flutter/material.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("title"),
),
body: Column(
children: [
InkWell(onTap: (){
_onAlertButtonsPressed(context,"test","title",(){},(){});
}, child: Text("test")),
],
),
);
}
}
_onAlertButtonsPressed(context,String desc,String title,onPressYes,onPressNo) {
return Alert(
context: context,
//style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
//style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
//color: HexColor("#5344ed")
),
DialogButton(
child: Text(
"No",
// style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
// color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
Try below code hope its helpful to you. remove Container and Widget
onAlertButtonsPressed(context, desc, title, onPressYes, onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
),
onPressed: onPressYes,
),
DialogButton(
child: Text(
"No",
),
onPressed: onPressNo,
)
],
).show();
}
class EditProductScreen extends StatefulWidget {
#override
_EditProductScreenState createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
#override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
**MouseRegion(
cursor: SystemMouseCursors.text,
child: TextFormField(),)**
}
}
MouseRegion is not working as expected.
When I hover the cursor over the TextFormField, the cursor is not getting changed.
Can someone please explain how to achieve this.
use RichText, full widget with selectable text
Text.rich(
TextSpan(
text: 'Phone us:',
style: TextStyle(
fontSize: 24,
),
children: [
TextSpan(
text: '+123 1231 231',
style: TextStyle(fontSize: 20),
///change your cusorStyle
mouseCursor: SystemMouseCursors.click,
recognizer: TapGestureRecognizer()
..onTap = () async {
///do the thing you want
final _url = "tel:+1 555 010 999";
await canLaunch(_url)
? await launch(_url)
: throw 'Could not launch $_url';
},
),
],
),
),
You need to wrap your TextFormField to IgnorePointer.
MouseRegion(
cursor: SystemMouseCursors.wait,
child: IgnorePointer(
ignoring: true,
child: TextFormField(),
),
)