Repository: flutter
Issue: [proposal] InkRipple and InkSplash implementations warrant improvements
Labels: framework,f: material design,c: proposal,team-design,triaged-design

Note: Design doc/proposal is in progress; will link it here when ready 👍🏻 

## Pre-issue notes: 

This issue is intended to organize/contextualize the work for several small PRs, related to various possible improvements to the user's and developer's interactions with the `InkRipple` and `InkSplash`. For all of the suggestions written below, unless explicitly specified otherwise, I've already gone through the process of making the improvements on other branches, but have decided to split up the work to make review/merging easier for everyone.

So, this is intended to be an issue spanning many small improvements, which I plan to address in individual PRs. Many of the small improvements have been brought up in other issues; the work described below fully encapsulates the improvements described in at least issues #20922 and #49957).

This issue also presupposes the virtue of the point made by Marc Glasberg here: https://github.com/flutter/flutter/issues/20922#issuecomment-487401588

> But users couldn't care less about the Material guidelines. They want a consistent experience, and they will judge your app according to that.... I'd suggest Flutter follows Android and you may open a ticket on the Material guidelines instead.

I work in apps that are being migrated from Android to Flutter, and can attest to how annoying it is to have different implementations of the same view in one user experience. If anyone disagrees vehemently with this general point, I'd be happy to chat about it and come to a consensus on how to proceed.

## Purpose:

This issue generally addresses the many small ways that the implementation and documentation of ink features (particularly, the `InkSplash` and `InkRipple`) can be improved. The purposes of these two implementations should be more clear for developers, and the implementations themselves should more accurately reflect the way they're implemented on Android, where users may see Flutter material widgets in the same user experience as an Android material view.

## Proposed/Planned Changes:

I've broken down the improvements into buckets of work that can be addressed in individual, smaller PRs. I have code written already, and I'm planning on putting up PRs for each of these, in the order that they're written here. Click below each for screenshots demonstrating the inconsistencies between Android and Flutter.

- [ ] **SplashFactory Test Coverage:** Currently, many tests fail after changing the default splash factory on the material Theme. To make the PR changing the default splash factory easier, test coverage should be improved for widgets using ink features, to be able to pass regardless of what the theme’s default splash factory is. We can take the opportunity here to consolidate some duplicated code for utils related to testing how ripples are drawn.

- [ ] **Default SplashFactory:** As a quick follow-up to the first PR, we should also change the default splash factory to the `InkRipple.splashFactory`, which is going to match the material animation for all Android APIs going forward. Currently, `InkSplash.splashFactory` is the default, which is an outdated choice, that's getting more outdated by the day.
- [ ] **SplashFactory Documentation:** `InkRipple`/`InkSplash` documentation should be more clear about their intended use cases. Specifically, it should state that the `InkRipple` is an updated version of the InkSplash, and that the two implementations represent the ripple animations seen on Android versions 9 and above (API 28+), and Android versions 5-8 (API 21-27), respectively.
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103396666-5a6f2180-4ae9-11eb-97ca-152b19d3bb08.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103396704-84284880-4ae9-11eb-9b46-ea0663ada74c.gif"></details>
- [ ] **Ripple Color:** The Flutter material ripple color is not exactly correct, which causes a slight inconsistency, most clearly visible in the colors of overlapping ripples, or on ripples on non-white backgrounds.
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103395848-11b56980-4ae5-11eb-9e70-f150a1a92aa1.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103395850-1417c380-4ae5-11eb-8929-5968755fe02f.gif"></details>
- [ ] **Ripple Initial Radius:** The initial radius of the `InkRipple` is 30% of its container’s largest dimension, but it should be 60%. Documentation of the Flutter implementation shows that it was intended to be 60%, so this is just a bug in the original implementation.
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103394297-87690780-4adc-11eb-85ae-0e1aa0b5c16f.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103394295-81732680-4adc-11eb-997e-29ad6e049d49.gif"></details>
- [ ] **Ripple Target Radius:** The target radius of the `InkRipple`/`InkSplash` not only lacks fidelity to the Android version (which is simpler/more readable, and more sensible), but is unnecessarily non-performant. Use the simpler logic, used in the Android source.
        <details><summary>Screenshots:</summary>
`InkSplash`: <img width="300" src="https://user-images.githubusercontent.com/7915388/103396982-f9484d80-4aea-11eb-9a36-92fb1d6421d7.gif">
The difference for the `InkRipple` is really hard to spot, but I'll make it clear in my PR. basically, you can't actually tell the difference of the size, except in how the target size affects the timing of the ripple's fade out animation. Especially with the other issues, it's not really worth adding a screenshot here for now.</details>
- [ ] **Position/Curves for Ripples/Splashes:** The initial position/position of ink features, as well as the curves they follow as they expand, lacks fidelity to the Android implementation. The difference in initial position is more noticeable, but these are likely good things to address at the same time.
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103396548-c3a26500-4ae8-11eb-8a36-8bafdb69dabc.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103396393-e2542c00-4ae7-11eb-98a5-0bdc9511aab2.gif">
<img width="300" src="https://user-images.githubusercontent.com/7915388/103396394-e41def80-4ae7-11eb-8d79-351ff2f41a32.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103396396-e54f1c80-4ae7-11eb-9c2c-dbbf8f078635.gif"></details>
- [ ] **Removing `InkRipple`'s highlight** The `InkRipple` should not have associated `InkHighlights` drawn for pressed gesture states. Remove it (or just make it fully transparent).
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103393753-47ecec00-4ad9-11eb-9129-d79664a2deca.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103394161-a915bf00-4adb-11eb-8988-53360284d19d.gif"></details>
- [ ] **Ink Feature Cancel Tap Logic:** The tap logic for when to initiate a splash is incorrect, as pointed out also by Marc Glasberg here: https://github.com/flutter/flutter/issues/20922#issue-353083144. It should be initiated on cancel or confirm of a tap, instead of on tapDown.
        <details><summary>Screenshots:</summary>
<img width="300" src="https://user-images.githubusercontent.com/7915388/103397588-de2b0d00-4aed-11eb-9ff4-b23437e3c4ad.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103397599-e5521b00-4aed-11eb-8769-2a6dc111bc15.gif">
<img width="300" src="https://user-images.githubusercontent.com/7915388/103397642-14688c80-4aee-11eb-8942-3da4d873edc9.gif">   <img width="300" src="https://user-images.githubusercontent.com/7915388/103397650-1af70400-4aee-11eb-89f4-1290947d536a.gif"></details>
  - [ ] Currently, it isn’t possible to make this completely in line with the Android implementation, because cancel events happen much more often in Flutter (cancels happen automatically after dragging far enough away from a pointer’s origin), but we can at least still trigger splashes on cancel, regardless of what triggers those cancellations.
  - [ ] **_(Probably a separate issue/needs input)_** So, separately, it would be nice to also address the limitation that we seem to have set on gestures for cancellation, where a tap is canceled after any drag event brings the pointer a 20 logical pixels away from its origin. On android, we are able to drag anywhere in the bounds of the gesture detector, without triggering a cancellation. I think this is clearly a preferred outcome, but I’m unsure about why it was done like this in the first place, and am curious what else I haven’t considered that might have made this limitation necessary.

## TL;DR:

Basically, there are a bunch of ways we can improve the Ripple/Splash animations, to have higher quality and fidelity to the Android versions. I have a bunch of the work planned and written, and I'm planning on opening PRs that just go down the list above. At the end of all this, the InkSplash an InkRipple should look pretty damn close to the way they do on Android, and hopefully, implementation/review will be pretty smooth/painless.