I have several custom widgets which alle accept the same data type as a parameter:
class Widget1 extends StatelessWidget {
Widget1({#required this.data});
final data;
}
class Widget2 extends StatelessWidget {
Widget2({#required this.data});
final data;
}
...
I have another widget which acts like a widget manager:
class WidgetManager extends StatelessWidget {
final data;
final type;
WidgetManager({this.data, this.type});
#override
Widget build(BuildContext context) {
if (this.type == 'Widget1') {
return Widget1(data: this.data);
} elseif (this.type == 'Widget2') {
return Widget2(data: this.data);
}
}
}
In PHP I could call the widgets with a string like this:
$widget_name = 'Widget1';
$widget = new $widget_name($data);
Is there any way to do a similar thing in flutter?
Like return this.type(data: this.data);?
Related
I found an excellent way to make a filter using both Equatable and Block
But I want to convert it to Get. I tried a lot for days, but I couldn't..Can I get help converting it to Get, please ?
The filter method consists of three classes, the first FilterEvent :
abstract class FilterEvent extends Equatable {
const FilterEvent();
#override
List<Object> get props => [];
}
class FilterLoad extends FilterEvent {
#override
List<Object> get props => [];
}
class LocationFilterUpdated extends FilterEvent {
final LocationFilter locationFilter;
const LocationFilterUpdated({required this.locationFilter});
#override
List<Object> get props => [locationFilter];
}
Second FilterState :
class FilterState extends Equatable {
const FilterState();
#override
List<Object> get props => [];
}
class FilterLoading extends FilterState {}
class FilterLoaded extends FilterState {
final Filter filter;
const FilterLoaded({this.filter = const Filter()});
#override
List<Object> get props => [filter];
}
Finally Block:
class FilterBlock extends Block<FilterEvent, FilterState> {
FilterBlock() : super(FilterLoading());
#override
Stream<FilterState> mapEventToState(FilterEvent event) async* {
if (event is FilterLoad) {
yield* _mapFilterLoadToState();
}
if(event is LocationFilterUpdated){
yield* _mapLocationFilterUpdated(event, state)
}
}
Stream<FilterState> _mapFilterLoadToState() async*{
yield* FilterLoaded(filter: Filter(locationsFilter: updatedLocationFilters));
}
Stream<FilterState> _mapLocationFilterUpdated(LocationFilterUpdated event , FilterState state) async*{
if(state is FilterLoaded){
final List<LocationFilter> updatedLocationFilters =
state.filter.locationsFilter.map((locationFilter) {
return locationFilter.id == event.locationFilter.id
? event.locationFilter
: locationFilter;
}).toList();
FilterLoaded(filter: Filter(locationsFilter: updatedLocationFilters));
}
}
}
Am just starting to learn Adroind and am coming up with an Audio player app and am stuck, I dont know how am going to insert the audio files in my Recycler Adapter for it to play. can someone help me out please?
public class AudioRecyclerViewAdapter extends RecyclerView.Adapter<AudioRecyclerViewAdapter.ViewHolder> {
// Global variables
ArrayList audios;
MainActivity mainActivity;
public AudioRecyclerViewAdapter(
// Local variables
MainActivity mainActivity, ArrayList<Audio> audios
) {
this.audios = audios;
this.mainActivity = mainActivity;
}
#NonNull
#Override
public AudioRecyclerViewAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Link to audio item layout
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.audio_item, parent, false);
return new ViewHolder(v);
}
/**
* Change item layout views
* #param viewHolder
* #param position
*/
#Override
public void onBindViewHolder(#NonNull AudioRecyclerViewAdapter.ViewHolder viewHolder, int position) {
// Get audio
Audio audio = audios.get(position);
// Update views
viewHolder.titleTextView.setText(audio.getTitle());
viewHolder.artworkHolder.setImageResource(audio.getImage());
viewHolder.audioLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Check if clicked song is active song.
if(audio.equals(mainActivity.activeAudio)) {
if(audio.isPlaying) {
viewHolder.playIcon.setImageResource(R.drawable.ic_pause_circle_outline_24);
mainActivity.pauseAudio(mainActivity.activeAudio);
} else {
viewHolder.playIcon.setImageResource(R.drawable.ic_play_circle_outline_24);
mainActivity.playAudio(mainActivity.activeAudio);
}
} else {
// Pause previous song
mainActivity.pauseAudio(audio);
// Update to current song
viewHolder.playIcon.setImageResource(R.drawable.ic_pause_circle_outline_24);
mainActivity.setActiveAudio(audio);
}
}
});
}
#Override
public int getItemCount() {
return audios.size();
}
/**
* Access item layout views
*/
public class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout audioLinearLayout;
TextView titleTextView;
ImageView playIcon;
ImageView artworkHolder;
RecyclerView audioRecyclerView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
audioLinearLayout = itemView.findViewById(R.id.playing_audio_linear_layout);
titleTextView = itemView.findViewById(R.id.playing_title_text_view);
playIcon = itemView.findViewById(R.id.playing_play_pause_image_button);
artworkHolder = itemView.findViewById(R.id.playing_audio_image_view);
audioRecyclerView=itemView.findViewById(R.id.audio_recycler_view);
}
}
}
I would like to create a class that will contain a few functions to be used in all the code.
I'm doing this:
MAIN CLASS
class ListaAbitudini extends StatefulWidget {
final Function scegliIcona;
ListaAbitudini({this.scegliIcona});
#override
State<StatefulWidget> createState() {
return new _ListaAbitudiniState();
}
}
class _ListaAbitudiniState extends State<ListaAbitudini> {
#override
Widget build(BuildContext context) {
widget.scegliIcona();
...
}
}
CLASS WITH THE FUNCTION
class FindIcone {
Icon scegliIcona(){ ... }
ListaAbitudini(scegliIcona);
}
The problem is that I have an error on this line: 'ListaAbitudini(scegliIcona);' saying that "ListaAbitudini must have a method body because FindIcone isn't abstract".
What am I doing wrong? HELP
The method you use is for parent widget to child widget. In your case you can Create new object of FindIcone and call the method.
class ListaAbitudini extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new _ListaAbitudiniState();
}
}
class _ListaAbitudiniState extends State<ListaAbitudini> {
#override
Widget build(BuildContext context) {
FindIcone().scegliIcona();
}
}
class FindIcone {
Icon scegliIcona() {
return Icon(Icons.ac_unit);
}
Also you can use provider.
// I cant find a way to pass a string from a class to another. They are both in the same screen and i want to pass the index from a pageview on class to another. Any help would be grateful!
//on the first class//
onPageChanged: (int index) {
_sendDataToAnotherClass(context, index);
_currentPageNotifier.value = index;
}),
),
);
}
void _sendDataToAnotherClass(BuildContext context, int index) {
final String texttosend = index.toString();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return new personaname(text: texttosend);
}
));
}
//on the second class//
final String text ;
personaname({Key key, #required this.text}) : super(key: key);
if your personaname is a class (just fyi if that is indeed a class the proper format is to capitalize the first letters of each word - PersonaName), and that class is a stateful widget you could pass the data down to it and do a call within the state to override the didUpdateWidget method to setState on data changes. This would mean you don't need the value notifier.
Something like this might do what you're looking for:
class PageViewHolder extends StatelessWidget{
PersonaName name = PersonaName(text: 'text',);
#override
Widget build(BuildContext context) {
return PageView(
onPageChanged: (p){
var textToSend = 'do logic to decide name';
name.text = textToSend;
},
);
}
}
class PersonaName extends StatefulWidget{
String text;
PersonaName({Key key, this.text}) : super(key: key);
#override
State<StatefulWidget> createState() =>_PersonaName();
}
class _PersonaName extends State<PersonaName>{
#override
Widget build(BuildContext context) {
return Text(widget.text);
}
#override
void didUpdateWidget(PersonaName oldWidget) {
super.didUpdateWidget(oldWidget);
if(widget.text != oldWidget.text){
setState(() {});
}
}
}
In this code I am trying to show list of Locations in a drop down menu. In here,I am working with a location model that consists of both name and uid. It works. However, I am not able to show the selected option to the user.
the object here for me is the Location( this.name, this.uid).
class DropButt extends StatelessWidget {
DropButt({Key key,this.locations,this.onchange});
// final String _selectedLocation='';
final List<Location> locations;
Function(Location) onchange;
#override
Widget build(BuildContext context) {
return DropdownButton<Location>(
//value:, here I donot know which value Should I put when I come to put //name it didnot accept it as dropdownbutton is of type location
items: locations.map((Location val) {
return new DropdownMenuItem<Location>(
value: val,
child: new Text(val.name),
);
}).toList(),
onChanged:(_){
onchange(_);
//here I will sink to the ream the value of th choosen location
},
);}
}
You would set the value of the currently selected location. It would need to be passed to this new custom stateless object.
Here's a working sample:
class HomePage extends StatefulWidget {
#override
State<StatefulWidget> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Location _selectedLocation;
final _locations = [
new Location("home", "1"),
new Location("office", "2"),
new Location("work", "3"),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Sample"),),
body: DropButt(
_selectedLocation,
locations: _locations,
onchange: (location) {
setState(() {
_selectedLocation = location;
});
},
),
);
}
}
class DropButt extends StatelessWidget {
DropButt(this.selectedLocation, {Key key, this.locations, this.onchange});
final Location selectedLocation;
final List<Location> locations;
Function(Location) onchange;
#override
Widget build(BuildContext context) {
return DropdownButton<Location>(
value: selectedLocation, // <--- this is the current selected object
items: locations.map((Location val) {
return new DropdownMenuItem<Location>(
value: val,
child: new Text(val.name), // <--- this is what the user sees
);
}).toList(),
onChanged: onchange,
);
}
}
class Location {
final String name;
final String uid;
Location(this.name, this.uid);
}