Add a link to navigator in a text widget - flutter

I want to show a link to seperate view inside a text widget
I tried adding Two Text Widgets and a flat button in between but it doesnt show as expected
How I want it to look like
<p>This is a sample text</p>
This is what i tried
Column(
children: [
Text('This is a '),
FlatButton(
onPress: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>View()))
}
child: Text('sample')
),
Text(' text')
]
)

TapGestureRecognizer _recognizer;
#override
void initState() {
super.initState();
_recognizer = TapGestureRecognizer()..onTap = (){
print("tapped");
};
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(text: 'This is a '),
TextSpan(text: 'sample', style: TextStyle(fontWeight: FontWeight.bold), recognizer: _recognizer),
TextSpan(text: ' text'),
],
),
),
),
);
}

Related

How to use focus on RichText in flutter?

I have a list of text span like this
var spans = [
TextSpan(text: content, style: style),
TextSpan(text: content, style: style)
//and 100 more
]
I am loading this inside SingleChildScrollView like this.
SingleChildScrollView(
controller: scrollController,
child: Text.rich(
TextSpan(children: spans),
),
)
Now My question is how can I shift focus between the TextSpan list?. Say I want to load TextSpan at position 10 from spans list at top of screen without manually scrolling.
You could add a WidgetSpan next to each of your TextSpan, so you can assign it a key property which would be a GlobalKey so you can access its BuildContext to call the method Scrollable.ensureVisible().
Here's a code sample inspired by an answer to a similar question:
class ScrollToTextSpanPage extends StatefulWidget {
const ScrollToTextSpanPage({Key? key}) : super(key: key);
#override
State<ScrollToTextSpanPage> createState() => _ScrollToTextSpanPageState();
}
class _ScrollToTextSpanPageState extends State<ScrollToTextSpanPage> {
final _keys = List<GlobalKey>.generate(
_kTextBlocks.length,
(_) => GlobalKey(),
);
void _goToSpan(int spanIndex) {
Scrollable.ensureVisible(
_keys[spanIndex].currentContext!,
alignment: 0.2,
duration: const Duration(milliseconds: 300),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scroll to TextSpan'),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => _goToSpan(8),
label: const Text('Go to span 8'),
icon: const Icon(Icons.navigate_next),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Text.rich(
TextSpan(
children: [
for (int i = 0; i < _kTextBlocks.length; i++) ...[
WidgetSpan(child: SizedBox(key: _keys[i])),
TextSpan(
text: 'Span $i\n',
style: const TextStyle(fontWeight: FontWeight.bold),
children: [
TextSpan(
text: '${_kTextBlocks[i]}\n\n',
style: const TextStyle(fontWeight: FontWeight.normal),
),
],
),
],
],
),
),
),
);
}
}
Try the sample on DartPad

How to navigate to respective page by tapping RichText in flutter

I am implementing RichText, in which while tapping the text i need to navigate to the respective page , i have did it using recognizer, but unable to navigate, any suggestion which could really helpful, pls suggest
RichText(
text: TextSpan(children: [
TextSpan(
text: ' ALREADY HAVE AN ACCOUNT ? ',
style: TextStyle(color: Colors.grey)),
TextSpan(
text: 'LOG IN',
recognizer: new TapGestureRecognizer()..onTap = () => {
Navigator.push(context, MaterialPageRoute(
builder: (context) => LoginPage()),
)
},
style: TextStyle(color: Colors.deepPurpleAccent)),
]))
try this:
RichText(text: TextSpan(children: [
TextSpan(
text: ' ALREADY HAVE AN ACCOUNT ? ',
style: TextStyle(color: Colors.grey)),
WidgetSpan(child: GestureDetector(child:Text('LOG IN', style: TextStyle(color: Colors.deepPurpleAccent),), onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => LoginPage()),
);
},)
]),)
How about wrapping RichText in an InkWell:
import 'package:flutter/material.dart';
class TextInkwellpage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Text InkWell'),
),
body: Center(
child: InkWell( // child tapped will fire onTap
child: RichText(
text: TextSpan(text: 'Inside RichText....', style: DefaultTextStyle.of(context).style),
),
onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => SomePage())),
// ↑ Navigate to new page here
),
)
);
}
}

How to add Progress Indicator on Cards while tap in Flutter?

I am using Cards in Flutter and want Progress Indicator at the left bottom position for 2 seconds while Tap on the card so that another page load successfully.
Does anyone know how to add?
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.setting),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
// I try this one but not working
// Flushbar(
//
// showProgressIndicator: true,
// duration: Duration(seconds: 2),
// );
getDetails().then((myCardlocations) {
Navigator
.of(context)
.pushNamed('/myCardlocations',
arguments: ObjectLocations(locations, 'myCardlocations'));
}
);
}
),
),
],
),
),
),
You can do something like this using Stack and CircularProgressIndicator..
class _MyWidgetState extends State<MyWidget> {
bool isLoading = false;
#override
Widget build(BuildContext context) {
return Container(
height: 130,
child: Stack(
children: [
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
setState(() {
isLoading = true;
});
getDetails().then((myCardLocations) {
setState(() {
isLoading = false;
});
// navigation code here
});
},
),
),
],
),
),
),
Align(
alignment: Alignment.bottomLeft,
child: isLoading
? Padding(
padding: EdgeInsets.fromLTRB(15,0,0,15),
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(),
),
)
: SizedBox(),
),
],
),
);
}
}
Edit:
Looks like I misunderstood the question a bit. Specifically, the place where to show the progress indicator. Anyways, if you get the idea, you can put the indicator at a different place as per your requirement.
There are certain things, which I would like to mention before I give the actual answer.
Read about Flutter.delayed constructor, very useful thing to make some thing wait for a while and do the operation by providing Duration. Whatever you want to do after that duration, it will implement in the callback function
Future.delayed(Duration(seconds: your_time, (){
//it will perform this operation after that much of seconds
}));
You can always show/hide a Widget using bool value, and make changes accordingly
Use a column and Add the LinearProgressIndicator at the end of the Widget. Show/hide it based up on the data
Also, use MediaQuery to give out the height. It is more efficient way of giving the dimensions according to all phone size. Like match-parent in Android Studio. Do the math accordingly, I have shown in the code also
Column(
children: [
Row(),
bool val ? LinearProgressIndicator() : Container() // Container() is nothing but an empty widget which shows nothing
]
)
Some heads up: I have not used getData, since it is not defined properly but you can call it the in function which I will show you in the code, that is pageTransit(). Follow the comments and you are good to go
class _MyHomePageState extends State<MyHomePage> {
// this takes care of the show/hide of your progress indicator
bool _showProgress = false;
// this takes care of the operation
void pageTransit(){
// first show when the ListTile is clicked
setState(() => _showProgress = true);
Future.delayed(Duration(seconds: 2), (){
// hide it after 2 seconds
setState(() => _showProgress = false);
// do the page trnasition here
//getDetails().then((myCardlocations) {
//Navigator.of(context).pushNamed('/myCardlocations',
//arguments: ObjectLocations(locations, 'myCardlocations'));
//}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: MediaQuery.of(context).size.height * 0.1,
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// use your items here, based upon the bool value show hide your
// progress indicator
Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () => pageTransit()
)
)
]
),
// show/hide in the card
_showProgress ? LinearProgressIndicator() : Container()
]
)
)
)
);
}
}
Result
Look at the ProgressIndicator, it remains there for 2 seconds, and then goes away
1. You need to define a GlobalKey for the Scaffold so that you can use a SnackBar (you can define the GloablKey in your page's State).
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
2. You need to set the key for the Scaffold.
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
...
3. You need to wrap the Card with a GestureDetector and set the onTap function to call showLoading which shows a SnackBar on the bottom of the screen. Call your getDetails function in the showLoading. Full code (except the define key step):
void _showLoading() {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
duration: new Duration(seconds: 2),
content: new Row(
children: <Widget>[
new CircularProgressIndicator(),
new Text("Loading...")
],
),
));
// call to your getDetails and its steps should be here
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("My app"),
),
body: Center(
child: GestureDetector(
child: Card(
child: Row(children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
)),
])),
onTap: () => _showLoading(),
)),
);
}
}
Note: you can also style the SnackBar.
Result:

How can reload page with new content in Flutter?

How can i create a button that when user click on the button, the page will refresh and show new content?
Call the setState(() {}) method. You need a StatefulWidget for that.
Your code will be something like
RaisedButton(
child : Text("Tap"),
onPressed : () {
setState(() {
// modifiy the state
})
}
),
Here is a Codepen example of the code below
class _MyWidgetState extends State<MyWidget> {
int counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: () {
setState(() {
counter++;
});
},
child: Text(
"Flat Button",
),
),
Text(
'Counter',
style: Theme.of(context).textTheme.headline4,
),
Text(
'$counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
);
}
}

Custom widget doesn't show

I'am trying to create a custom widget CarteSim and I'am trying to call it everytime I click on Floating Action Button , but unfortunately it doesn't show when I call it inside the button , but it shows when I call it in the Scaffold , please who has ever experience that
here s my code
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
title: Text(" INWI "),
),
body: SingleChildScrollView(
child: Container(
child: Center(
child: Column(
children: <Widget>[
DropdownButton<String>(
items: _type.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String newValueSelected) {
setState(() {
this._currentItemSelected = newValueSelected;
});
},
value: _currentItemSelected,
),
Divider(
color: Colors.black,
),
new Row(
children: [
new Text(" type client supporte * carte avec 1 cin"),
new Checkbox(value: _isChecked, onChanged: (bool value){ onChanged(value);}),
]
),
Divider(
color: Colors.black,
),
new Column(
children: <Widget>[
CarteCin(),
CarteSim(),
]
)
],
),
),
)
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Column(
children: <Widget>[
CarteSim(),
]
);
},
child: Icon(Icons.add),
backgroundColor: Colors.pink,
),
);
}
]
}
you are misunderstanding the process. The onPressed key actually used for call actions on press the floatingActionButton. You can write functions there, like you can update your state or print anything on your console or call an API to get data. But you can't display any widget from there.
Now what you're trying to do, that can be resolved like this. Whenever you press that button you should update your state, i.e bool show. Then modify your Column children based on that show state.
Here is an example how tu update the UI in flutter
class FrontPage extends StatefulWidget {
#override
_FrontPageState createState() => _FrontPageState();
}
class _FrontPageState extends State<FrontPage> {
bool currentStateShowsThis;
initState() {
currentStateShowsThis = false;
super.initState();
}
Widget build(BuildContext context) {
final color = currentStateShowsThis ? Colors.blue : Colors.red;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
title: Text(" INWI "),
),
body: SingleChildScrollView(
child: Container(
child: Center(
child: Column(
children: <Widget>[
Container(width: 100, height: 100, color: color,) // alternatively you can change the widgets being displayed
],
),
),
)
),
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
currentStateShowsThis = !currentStateShowsThis;
});
},
child: Icon(Icons.add),
backgroundColor: Colors.pink,
),
);
}
}
In your example "the button" will call back the
onPressed:
Which will only create the widgets in that method (Column ...) and not place them in a the layout.