skip to Main Content

I am in the process of learning Flutter and have built a simple xylophone app. It works just fine, but I noticed that it only plays the sounds when I release my finger from the key. If I touch the key and keep my finger pressed down, nothing happens. Only when I lift it the sound is played.

According the Flutter documentation a function that is specified in onPressed (a requirement for the Button class) should be executed when the button is pressed. But that is not what is happening in my case.

How can I change to code to play the sound as soon as I touch a key?
I want to be able to keep my finger on the screen, scroll along all the keys and hear their sounds, like you do on a real xylophone.

I have looked online to solve this, but have not found anything that helps.

My code:

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';

var KeyColors = [
  Colors.red,
  Colors.orange,
  Colors.yellow,
  Colors.greenAccent,
  Colors.green[800],
  Colors.lightBlue,
  Colors.blue[800],
  Colors.purple,
];

void main() {
  runApp(XylophoneApp());
}

class XylophoneApp extends StatelessWidget {
  const XylophoneApp({super.key});

  void playSound(int num){
    final player = AudioPlayer();
    player.play(AssetSource('$num.wav'));
    }

  Expanded buildKey(int number){
    return Expanded(
      child: Container(
        margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
        child: ElevatedButton(
          child: Text(''),
          onPressed: (){
            playSound(number+1);
          },
          style: ElevatedButton.styleFrom(
            backgroundColor: KeyColors[number],
            ),
        ),
      ),
    );
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: SafeArea(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              for (int i = 0; i < 8; i++) buildKey(i)
            ],
          ),
        ),
      ),
    );
  }
}

2

Answers


  1. Approach 1: Wrap with Listener widget and add onPointerDown property

      Expanded buildKey(int number) {
        return Expanded(
          child: Container(
            margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
            child: Listener(
              onPointerDown: (event) {
                playSound(number + 1);
              },
              child: ElevatedButton(
                child: Text(''),
                onPressed: () {},
                style: ElevatedButton.styleFrom(
                  backgroundColor: KeyColors[number],
                ),
              ),
            ),
          ),
        );
      }
    

    Approach 2: Using GestureDetector or InkWell widget with onTapDown property:

      Expanded buildKey(int number) {
        return Expanded(
          child: GestureDetector(
            onTapDown: (details) {
              playSound(number + 1);
            },
            child: Container(
              color: KeyColors[number],
              margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
              child: Text(''),
            ),
          ),
        );
      }
    
    Login or Signup to reply.
  2. Use InkWell Widget above the button instead of onPressed attribute

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search