Flutter | TrimViewer of video_trimmer plugin isn't displayed - flutter

I'm using video_trimmer plugin and trying to make the app able to trim the videos.
I could show video playback area with the widget:
VideoViewer(trimmer: _trimmer)
However, video trimmer area wasn't displayed.
TrimViewer(
trimmer: _trimmer,
viewerHeight: 50.0,
viewerWidth: MediaQuery.of(context).size.width,
maxVideoLength: const Duration(seconds: 10),
onChangeStart: (value) => _startValue = value,
onChangeEnd: (value) => _endValue = value,
onChangePlaybackState: (value) =>
setState(() => _isPlaying = value),
)
I wrote these widgets inside of Column widget, but TrimViewer are ignored.
I can't find why this widget is not displayed.
Thank you.

Related

How to get Integer value from a user through a TextField that uses an onChanged method in Flutter

It's worth noting that I am quite new to flutter so a lot of work done is based on tutorials or videos...
Apologies if the question seems obvious.
//Build Length Box.
Widget buildLength() => buildHeader(
header: 'House Length: ',
child: Row(
children: [
// I want to be able to get user input(has to be an integer value for calculations further in the program)
// from this child: Text(), At the moment I am only able to get the input from the slider...
//I want to be able to use the slider or the text next to it.
//The first child widget should preferably work with the same onChangedLength method the slider uses...
Expanded(
flex: 1,
child: Text(
length.toString(),
style: TextStyle(color: Colors.white),
),
),
Expanded(
flex: 9,
child: Slider( //TODO: Decide on the correct parameters for the slider, min/max/etc...
label: length.toString(),
value: (length ?? 0).toDouble(),
min: 0,
max: 100,
divisions: 100,
onChanged: (length) => onChangedLength(length.toInt()),
),
),
],
),
);
The onChanged Method was mentioned here as well.
onChangedLength: (length) => setState(() => this.editLength = length),
The tutorial I am busy with uses the onChanged, however if this wont work I am open to other methods I can use.
You are setting the changed value of the length into editLength.
yet you using length.toString() to display,
if your declared variable is int editLength
editLength.toString() // Text Widget
label: length.toString(), // Slider Widget
value: (editLength ?? 0).toDouble() // Slider Widget
or
if your declared variable is int length
onChanged: (newLength) => onChangedLength(newLength.toInt()), // Slider widget
onChangedLength(newLength) => setState(() => this.length = newLength); // onChangedLength function

Widget Test Doesn't Fire DropdownButton onChanged

I have a widget test that taps an item in the DropdownButton. That should fire the onChanged callback but it doesn't. Here is the test code. The mock is Mockito.
void main() {
//Use a dummy instead of the fake. The fake does too much stuff
final mockServiceClient = MockTheServiceClient();
final apiClient = GrpcApiClient(client: mockServiceClient);
when(mockServiceClient.logEvent(any))
.thenAnswer((_) => MockResponseFuture(LogEventResponse()));
testWidgets("select asset type", (tester) async {
//sets the screen size
tester.binding.window.physicalSizeTestValue = const Size(3840, 2160);
// resets the screen to its orinal size after the test end
addTearDown(tester.binding.window.clearPhysicalSizeTestValue);
await tester.pumpWidget(AssetApp(apiClient), const Duration(seconds: 5));
//Construct key with '{DDLKey}_{Id}'
await tester
.tap(find.byKey(ValueKey("${assetTypeDropDownKey.value}_PUMP")));
await tester.pumpAndSettle(const Duration(seconds: 5));
verify(mockServiceClient.logEvent(any)).called(1);
});
}
This is the build method of the widget:
#override
Widget build(BuildContext context) {
return DropdownButton<DropDownItemDefinition>(
underline: Container(),
dropdownColor: Theme.of(context).cardColor,
hint: Text(
hintText,
style: Theme.of(context).textTheme.button,
),
//TODO: Use the theme here
icon: Icon(
Icons.arrow_drop_down,
color: Theme.of(context).dividerColor,
),
value: getValue(),
onChanged: (ddd) {
setState(() {
onValueChanged(ddd!);
});
},
items: itemss.map<DropdownMenuItem<DropDownItemDefinition>>((value) {
return DropdownMenuItem<DropDownItemDefinition>(
key: ValueKey(
"${(key is ValueKey) ? (key as ValueKey?)?.value.toString() :
''}_${value.id}"),
value: value,
child: Tooltip(
message: value.toolTipText,
child: Container(
margin: dropdownPadding,
child: Text(value.displayText,
style: Theme.of(context).textTheme.headline3))),
);
}).toList(),
);
}
Note that the onValueChanged function calls the logEvent call. The onChanged callback never happens and the test fails. This is the code it should fire.
Future onAssetTypeChange(DropDownItemDefinition newValue) async {
await assetApiClient.logChange(record.id, newValue, DateTime.now());
}
Why does the callback never fire?
Note: I made another widget test and the Mock does verify that the client was called correctly. I think there is some issue with the callback as part of the widget test.
You need to first instruct the driver to tap on the DropdownButton itself, and then, after the dropdown popup shows up, tap on the DropdownMenuItem.
The driver can't find a DropdownMenuItem from the dropdown if the dropdown itself is not active/painted on the screen.

On web, how do I control the visibility icon that automatically appears on a focused TextFormField that has an obscureText property set to true?

Here's my code for the password field:
TextFormField(
obscureText: isObscure,
decoration: InputDecoration(
suffix: TextButton(
child: isPasswordObscure
? Text(
'Show',
style: TextStyle(color: Colors.grey),
)
: Text(
'Hide',
style: TextStyle(color: Colors.grey),
),
onPressed: () {
setState(() { isObscure = !isObscure; });
},
),
),
)
If I run it, the password field would look like this:
If you review my code, I only specified a text button and not an icon as the suffix. The visibility icon was added by Flutter Edge and when I click on it, it only changes its icon and does not unobscure or obscure the text field.
What I want to know is how do I change or remove the icon? And maybe also give it a callback so it knows what to do when I click on it.
The problem doesn't exist on mobile, only on browsers desktop Edge.
Edit:
I tried setting suffix and suffixIcon to null but the visibility icon is still showing.
Update: I've discovered that the problem only exists on MS Edge.
If you wants to turn off the visibility icon set onPressed: () {},
also if you want to remove the visibility icon form overview wrap it with opacity widget
Opacity(
opacity: 0.0,
child: textButton(),
Please find the below code sample to include the visibility option for the textField. by including a variable _isObscured in a stateful widget. we have implemented it with the auto obscure after 2 second delay.
Center(child: TextField(
obscureText: _isObscured,
decoration : InputDecoration(
suffix:InkWell(
onTap: (){
setState(() => this._isObscured =
!this._isObscured);
Future.delayed(Duration(seconds: 2), (){
setState(() => this._isObscured =
!this._isObscured);
});
},
child: Icon( Icons.visibility),
),
),
),
),
),
I found a solution:
// the magic function
void fixEdgePasswordRevealButton(FocusNode passwordFocusNode) {
passwordFocusNode.unfocus();
Future.microtask(() {
passwordFocusNode.requestFocus();
js.context.callMethod("fixPasswordCss", []);
});
}
// widget code
child: TextField(
onChanged: (_) async {
fixEdgePasswordRevealButton(passwordFocusNode);
},
focusNode: passwordFocusNode,
obscureText: true,
// end of index.html
window.fixPasswordCss = () => {
let style = document.createElement('style');
style.innerHTML = '::-ms-reveal { display: none; }';
document.head.appendChild(style);
}
</script>
</body>
Also posted on the relevant issue.

Flutter TextEditingController retain value without hitting done button

Simple Add Place widget
Title Text Field
Container - Render image from camera
Button - Activates camera device
I thought having a controller connected to TextField would automatically save the state of the input value. However, from my example, if I input the text without click "done" and immediately click on "Take Picture" button. The TextField input value is cleared after coming back from camera operation.
How to Reproduce Problem:
Input text into the field
Immediately click on the Camera button without click done / check or hit enter on the keyboard
Take a picture confirm.
Come back to page the TextField is empty
Example Code:
AddPlacePage StatefulWidget
Column(
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: 'Title'),
controller: _titleController,
),
ImageInput(),
],
),
ImageInput StatefulWidget
class _ImageInputState extends State<ImageInput> {
File _storedImage;
Future<void> _takePicture() async {
final imageFile = await ImagePicker.pickImage(
source: ImageSource.camera,
maxWidth: 600,
);
setState(() {
_storedImage = imageFile;
});
...
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Container(
...
child: _storedImage != null
? Image.file(
_storedImage,
fit: BoxFit.cover,
width: double.infinity,
)
: Text(
'No Image Taken',
textAlign: TextAlign.center,
),
alignment: Alignment.center,
),
Expanded(
child: FlatButton.icon(
icon: Icon(Icons.camera),
label: Text('Take Picture'),
textColor: Theme.of(context).primaryColor,
onPressed: () => _takePicture(),
),
),
],
);
}
}
Question:
How can I modify TextField's controller to retain input value even after exiting the application to access device camera?
TextField(
decoration: InputDecoration(labelText: 'Title'),
controller: _titleController,
),
I did try to create a local variable and try to use onChange:
String _inputValue
build(BuildContext context){
...
TextField(
decoration: InputDecoration(labelText: 'Title'),
controller: _titleController,
onChange: (value) => _inputValue = value;
),
However the effect is the same once returning from the camera as Flutter re-reders the page, both _inputValue and _titleController.text is cleared.
Example code:
https://github.com/erich5168/flutter_camera_example
You can use share preferences to save the String to device then call it when you back to text field. This is how I implement:
class LocalStorage {
static SharedPreferences instance;
static Future init() async {
instance = await SharedPreferences.getInstance();
}
static dynamic getValue(String key, dynamic emptyValue) {
if (LocalStorage.instance.containsKey(key)) {
return LocalStorage.instance.get(key);
}
return emptyValue;
}
}
set it to text field:
TextEditingController _usernameController =
new TextEditingController(text: LocalStorage.getValue('UserName', ''));

control & disable a dropdown button in flutter?

I wanted to control a drop-down button and make it unclickable using a button.
Is there any way to make it disable. Basically not allowing it able to change.
new DropdownButton(
value: animalName,
items: animals.map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {
setState(() {
animalName = value;
});
},
),
So this is the code I currently use on the drop-down button, but i cant disabled it.
Found this in the DropdownButton docs:
If items or onChanged is null, the button will be disabled, the down arrow will be grayed out, and the disabledHint will be shown (if provided)
DropdownButton(
onChanged: null,
items: [...],
)
This isn't what you want to hear, but I don't think there's currently an easy way. I experimented with simply removing all the items and that causes a nice little crash. Maybe worth raising an issue with the flutter people on github...
There is an alternative that may be good enough for you for now. If you wrap your DropdownButton in an IgnorePointer, when you want it to be disabled you can change IgnorePointer's ignoring property to true.
That way if the user taps on it, it won't do anything.
But you'll probably want to indicate to the user somehow that it's disabled as well, something like setting the hint text (as it's grey).
child: new IgnorePointer(
ignoring: true,
child: new DropdownButton(
hint: new Text("disabled"),
items: ["asdf", "wehee", "asdf2", "qwer"].map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {},
),
You can make DropdownButtonFormField or DropdownButton disabled if set onChanged to null, and if you want that dropdown still shows selected value you must set disabledHint. For example:
DropdownButtonFormField<String>(
disabledHint: Text(_selectedItem),
value: _selectedItem,
onChanged: enabled ? (value) => setState(() => _selectedItem = value) : null,
items: items.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem(
value: item,
child: Text(item),
);
}).toList(),
)
Just wrap it with IgnorePointer widget to make DropdownButton disable
IgnorePointer(
ignoring: enabled,
child: new DropdownButton(
value: animalName,
items: animals.map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {
setState(() {
animalName = value;
});
},
),
);
If items or onChanged is null, the button will be disabled, the down
arrow will be grayed out, and the disabledHint will be shown (if
provided)
So something like this should work:
DropdownButton<String>(
...
onChanged: this.enabled ? (id) => setState(() => this.id = id) : null,
)
okay, i found a trick that satisfied me
i wanted it hide/show the DropdownButton depending on CheckboxListTile
in StatefulWidget Class
first create a function ex:
_buildDropDown(bool enable) {
if (enable) {
return DropdownButton<String>(
hint: Text("Hint"),
items: <String>[
'item 1',
'item 2',
'item 3',
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (value) {},
);
} else { // Just Divider with zero Height xD
return Divider(color: Colors.white, height: 0.0);
}
}
and now in build
bool enable = true;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CheckboxListTile(
title: const Text('Switcher'),
selected: true,
value: enable,
onChanged: (bool value) {
setState(() {
enable = value;
});
},
),
_buildDropDown(enable),
],
);
}
now every time you change enable it will display and hide the DropdownButton
DropdownButtonFormField(
onChange: isDisable ? null : (str){
},
disabledHint: isDisable ? null : Text('Your hint text'),
...
)
For disable
onChange: null
For disable Caption
disabledHint: Text('Your hint text')
//add widget'AbsorbPointer' true-disable,false-enable
// isEditable = ture
AbsorbPointer(
absorbing: isEditable
DropdownButton(
onChanged: null,
items: [...],
)
)
Simple:
decoration:InputDecoration(enabled: false),