slider icon indicating copy to clipboard operation
slider copied to clipboard

Can't touch off the side

Open ToyboxZach opened this issue 2 years ago • 14 comments

I have a slider with a custom thumb

function SliderThumb() {
  return (
    <View
      style={{
        backgroundColor: colors.lightColor,
        width: 20,
        height: 20,
        borderRadius: 5,
        borderWidth: 2,
        borderColor: colors.lightBlue,
      }}
    />
  );
}

 <RangeSlider
        onSlidingStart={() => {
          setScrollEnabled?.(false);
        }}
        onSlidingComplete={() => {
          setScrollEnabled?.(true);
        }}
        minimumValue={0}
        trackHeight={4}
        maximumValue={tracks.length - 1}
        step={1}
        style={{ paddingHorizontal: 10, height: 40, width: "100%", backgroundColor: "blue" }}
        range={value}
        thumbSize={100}
        onValueChange={setValue}
        inboundColor={colors.ToyboxAccentColor}
        outboundColor={colors.darkBorder}
        crossingAllowed={true}
        CustomThumb={(cur) => {
          return <SliderThumb key={cur.thumb} />;
        }}
        CustomMark={(index) => {
          const inRange = index.value > value[0] && index.value < value[1];
          return (
            <View
              style={{
                height: 12,
                backgroundColor: inRange ? colors.ToyboxAccentColor : colors.darkBorder,
                width: 2,
              }}
            />
          );
        }}
      />

And its working great overall, but my design has the thumbs go off the edge of the track.

I'm able to increase the vertical touch target by changing the height on the view, but I can't figure out how to extend the touch distance off the side

image

Touching the left half of the thumb doesn't work and I can't figure out how to extend any of the touch target without also extending the track.

I would expect any touch within the blue part to work for the touch.

Same issue comes up without custom marks/custom thumbs

Is there a prop I am missing, or is this not supported?

ToyboxZach avatar Oct 18 '23 22:10 ToyboxZach

I reproduced your test case here

I don't understand why you say that the blue part doesn't respond to your touches. However, I noticed that the cursor is not always a pointer as you could expect. This is because the thumbs have "pointer-events: none" on them. Only the container view responds to touches. However, you can solve this by setting: "cursor: pointer" to the slider style. See my fix in the snack above.

Sharcoux avatar Oct 26 '23 14:10 Sharcoux

But you can't start the drag on the side there, it doesn't work which is the problem

ToyboxZach avatar Oct 26 '23 15:10 ToyboxZach

In the snack, I can move the thumb even if I start pressing on the blue area. Is the probleme related to the onSlidingStart event?

Sharcoux avatar Oct 27 '23 23:10 Sharcoux

Sorry maybe my case wasn't clear it's if you touch the edge of the slider, on the knob, to the left of the actual line, but still in the blue area. It does accept the click

ToyboxZach avatar Oct 31 '23 19:10 ToyboxZach

Sorry maybe my case wasn't clear it's if you touch the edge of the slider, on the knob, to the left of the actual line, but still in the blue area. It doesn't accept the click

ToyboxZach avatar Oct 31 '23 19:10 ToyboxZach

Your case is still not clear. Can you try to explain exactly what you are trying to achieve, what is happening instead, and why the provided snack doesn't solve your issue?

Sharcoux avatar Oct 31 '23 20:10 Sharcoux

So say the blue area is what is between the |

|xxx-----------------xxx|

The slider bar is the -

The slider does not accept touches on the xxx when it should because the thumb goes past the - and into the x area

ToyboxZach avatar Oct 31 '23 20:10 ToyboxZach

I have this when I try on the snack. Is it not the expected behavior?

slider

Sharcoux avatar Nov 01 '23 12:11 Sharcoux

Ah I see the problem, I am using the responsive mode on the browser/apps. So the touch events seem to be broken off the side, but the cursor ones work just fin

ToyboxZach avatar Nov 01 '23 14:11 ToyboxZach

And it doesn't work on the mobile versions of that link either updated with more obvious margins: https://snack.expo.dev/nzxuH2ghc

ToyboxZach avatar Nov 01 '23 16:11 ToyboxZach

Indeed... Ok, now I think I understand the problem. The issue is that, solving that will be quite troublesome, and I'm not sure I'll have the time soon for such a refacto. I'll write down the steps here if someone wants to give it a try.

The issue is that the ResponderView, in charge of listening to the user touches, is inside the containing view. So, the padding of that view won't respond to touches.

To solve this, we need to:

  1. Create a ContainerView that wraps the current View from Slider and RangeSlider components
  2. In that ContainerView we need to access the ref of the ResponderView. If no ref was provided by the user, we need to create one. We need that so we can call measureLayout in order to know the offset of the ResponderView relative to the ContainerView.
  3. The ContainerView should receive the onPress, onMove and onRelease listeners, and the responder events from the user. It should create its own set of responder events, just like the ResponderView, except that the eventToValue method should take in consideration the offset of the ResponderView. So, we need to call measureLayout to get that offset. Be careful, if the user provided responder events, they should be called too.
  4. Remove the code relative to responding to touches from the ResponderView. We don't need it anymore
  5. Rename ResponderView into SliderView
  6. Rename ContainerView into ResponderView

Sharcoux avatar Nov 01 '23 18:11 Sharcoux

Curious your opinion,

Would it also in theory work if we can just apply the padding to the responder view? So if I were to add an extra prop: horizontal padding, and just apply that directly to the responder view, would that work? Or would that break a bunch of other things?

Obviously that's not an ideal solution, but does unblock me.

ToyboxZach avatar Nov 01 '23 18:11 ToyboxZach

No, a padding in the responder view would mess up the computation of the positions for the thumb relative to touches. That could be solved, but require an extra work. Instead of spending time in a workaround, it would be better to directly spend that time on the proper solution. But don't worry, that will be fixed. It's just that, right now, it would be a bit too much for my plate. Anyway, I think that slideOnTap option makes your use case "ok" for users, even if not perfect.

Sharcoux avatar Nov 01 '23 18:11 Sharcoux

Thanks! I was just probing how complicated it would be. I agree the slideOnTap makes it work great if you know that it works that way

ToyboxZach avatar Nov 01 '23 18:11 ToyboxZach

I fixed this in version 8.0.0. Now, the padding area should respond to touches. Please report any bug.

Sharcoux avatar Oct 19 '24 11:10 Sharcoux