You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android/iOS/React Native实现类Doodle拖拽式时间范围选择器?

Hey there! Let's tackle your question about building a Doodle-style drag-and-drop time range picker across platforms, plus troubleshoot the issues you're facing with your Android implementation.

Android

  • TimeRangePickerDialog: A lightweight, customizable library that natively supports drag-based time range selection. It handles edge cases like invalid range overlaps and integrates smoothly with standard Android UI components.
  • MaterialTimeRangePicker: Built on Material Design guidelines, this library offers a modern, intuitive UI for time range adjustments via drag gestures. It works seamlessly if you need to embed the picker within a RecyclerView.
  • Material RangeSlider: While not a dedicated time picker, you can adapt the official Material Components RangeSlider to represent time intervals. Pair it with a custom adapter to map slider positions to time values, and add drag handlers for range tweaks.

iOS

  • TimeRangePicker: A Swift-native library designed specifically for horizontal/vertical time range selection with smooth drag interactions. It supports both 12-hour and 24-hour formats, with full customization for matching Doodle's UI style.
  • CRRangeSlider: A robust range slider library that handles drag gestures for selecting start/end values. Combine it with a time formatter to convert slider positions into readable time slots.
  • CalendarKit: A scheduling-focused library that includes drag-enabled time range selection components—perfect for building Doodle-like scheduling flows.

React Native

  • react-native-time-range-picker: A cross-platform library built explicitly for drag-and-drop time range selection. It works on both iOS and Android, supports custom styling, and handles touch events without sync issues.
  • react-native-slider: The popular slider library can be configured as a range slider. Wrap it in a custom component to map slider positions to time values and add drag handlers for adjusting ranges.
  • react-native-calendar-range-picker: While focused on date selection, many variants include drag-supportive time range pickers, ideal for end-to-end scheduling interfaces like Doodle.
Troubleshooting Your Android Implementation

Looking at your RecyclerView + DrawingView code, here are targeted fixes for the issues you mentioned:

  1. Drag & RecyclerView Sync Issues

    • Remove the delayed Handler in touch_move—the delay is causing desync. Instead, scroll the RecyclerView immediately when the touch position changes:
      private void touch_move(float x, float y) {
          float dy = y - mY;
          if (Math.abs(dy) >= TOUCH_TOLERANCE) {
              // ... your existing path logic ...
              
              // Scroll instantly with the touch delta
              int scrollDelta = (int) dy;
              mListView.scrollBy(0, scrollDelta);
              
              mY = y;
              circlePath.reset();
              circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
              invalidate(); // Force redraw to update the path
          }
      }
      
  2. Scroll Malfunction

    • Prevent DrawingView from consuming all touch events. Override onInterceptTouchEvent to return false when you want the RecyclerView to handle scrolling, or call requestDisallowInterceptTouchEvent(false) when drag isn't active.
    • Check for conflicting touch listeners between RecyclerView and DrawingView—implement a custom OnItemTouchListener to coordinate interactions.
  3. Incorrect Child View Retrieval

    • To get the child view matching the dragged time range, calculate the corresponding position using the RecyclerView's layout manager:
      // Get the visible item position based on touch y-coordinate
      int position = layoutManager.findFirstVisibleItemPosition() + 
          (int)((y - mListView.getTop()) / layoutManager.getChildAt(0).getHeight());
      View targetView = layoutManager.findViewByPosition(position);
      
    • Use layoutManager.getPositionForView(view) to confirm the position of any retrieved child view.
  4. General Code Cleanup

    • Move mPaint initialization into DrawingView for better encapsulation.
    • Avoid recreating Handler and Runnable instances in touch_move—create a single instance in DrawingView to prevent memory leaks.
    • Ensure invalidate() is called in touch_move and touch_up to trigger proper redraws.

内容的提问来源于stack exchange,提问作者Vinayak B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:54:00