DEV Community

Cover image for HarmonyOS Development: Customize a Clip Double Slider Component
程序员一鸣
程序员一鸣

Posted on

HarmonyOS Development: Customize a Clip Double Slider Component

Foreword 

this article is based on Api12 

some time ago, a small partner said a need to realize the function of editing an audio track. However, he was busy with his work and did not have time to do it. I am very sorry. Now that I have a little leisure time, I have started to realize it. I hope I can help friends who have this need. 

Since it is a function of editing and interception, audio and video are the same, except that the tracks and progress are different, but the dragging sliders are similar. Apart from the common use of audio and video, scenes with two-way sliding requirements can also be met. 

At present, the simple implementation effect is as follows, and various styles such as color can be dynamically set. 

The general content of this article is as follows: 

1. How to realize such a double slider component

2. Overview of code implementation

3, open source address and function use

4. Relevant summary

first, how to achieve such a double sliding component 

the first is the UI view, which can be divided into three or two layers. If there are three layers, the bottom track is one layer, the border is one layer, and the two sliders are one layer. If there are two layers, the bottom track and border are one layer, and the upper two sliders are one layer. 

The most important thing is the gesture of the two sliders. In addition to moving with the gesture, the slider should also record the position of the last gesture lift to facilitate continuous sliding. It is recommended to use onTouch event instead of gesture event here, because onTouch records coordinates more accurately and can move components smoothly.

It should be noted that the left and right sliding blocks need to be set with the maximum and minimum valves, that is to say, the left cannot slide beyond the right position, and the right cannot slide beyond the left position, and of course, cannot exceed the left and right positions of the track. 

Since the sliding display is coordinates, the final percentage needs to be calculated using the coordinates and the overall width of the track, which needs to be noted. 

II. Overview of Code Implementation 

in the code here, I AM also divided into three layers, the bottom track, the Middle Border and the upper slider according to the first one. 

We try not to use my default track, because the default is only a simple implementation of the audio track, and does not draw according to the frequency of video or audio, so it does not meet the actual development needs, so, for this, I threw out a method of passing views, you can implement this method to pass their own components. 

Bottom track


 

@BuilderParam trackLayout?: (leftProgress: number, rightProgress: number, viewWidth: number) => void //自定义的轨道
Enter fullscreen mode Exit fullscreen mode

        if (this.trackLayout != undefined) {
          this.trackLayout(this.leftProgress, this.rightProgress, this.viewWidth)
        } else {
          TrackView({
            leftProgress: this.leftProgress,
            rightProgress: this.rightProgress,
            viewWidth: this.viewWidth,
            trackAlignmentWidth: this.trackAlignmentWidth,
            trackSelectColor: this.trackSelectColor,
            trackNormalColor: this.trackNormalColor
          })
        }
Enter fullscreen mode Exit fullscreen mode

in the business layer, it is enough to implement trackLayout, and some special styles can be implemented according to the progress of the left and right, as well as the width of the components.

 


  @Builder
  trackLayout(leftProgress: number, rightProgress: number, viewWidth: number) {

  }
Enter fullscreen mode Exit fullscreen mode

Middle Border 

the Middle Border has nothing to say, it is a simple border. Of course, I also threw out a method to set the border by myself.

 

if (this.trackBgLayout != undefined) {
            this.trackBgLayout()
          } else {

            Column().width("100%")
              .height("100%")
              .border(this.trackBgBorder)

          }
Enter fullscreen mode Exit fullscreen mode

Upper slider 

the upper slider, the most important is to control the gesture of its slider, whether left or right, be sure to record the coordinates of the last lift, the other is to control the maximum movement distance of the left and right, the other to nothing, the main code is as follows:

 

Column() {
        if (this.leftPointerLayout != undefined) {
          this.leftPointerLayout()
        } else {
          Divider()
            .strokeWidth(this.pointerLineWidth)
            .height(this.pointerLineHeight)
            .vertical(true)
            .lineCap(this.pointerLineCap)
            .color(this.pointerLineColor)
        }
      }
      .width(this.pointerWidth)
      .height(this.pointerHeight)
      .justifyContent(FlexAlign.Center)
      .borderRadius(this.leftPointerBorder)
      .backgroundColor(this.leftPointerBgColor)
      .margin({ left: this.trackMarginLeft })
      .onTouch((event) => {
        switch (event.type) {
          case TouchType.Down: 
            this.pointerLeftMargin = event.touches[0].x
            break;
          case TouchType.Move:
            let rightMargin = this.viewWidth - this.trackMarginRight - Number(this.pointerWidth)
            let upData = event.touches[0].displayX
            let moveX = upData - this.viewMarginLeft
            let pointerValue = moveX - this.pointerLeftMargin
            if (pointerValue >= 0 && (pointerValue + Number(this.pointerWidth)) <= rightMargin) {

              this.trackMarginLeft = pointerValue
            }
            let percentage = this.trackMarginLeft / (this.viewWidth - Number(this.pointerWidth) * 2) //百分比
            let progress = Math.round(percentage * 100) //进度
            this.leftProgress = progress
            if (this.onLeftProgress != undefined) {
              this.onLeftProgress(progress)
            }
            break
          case TouchType.Up: 
            if (this.onLeftEndProgress != undefined) {
              this.onLeftEndProgress(this.leftProgress)
            }
            break
        }
      })
Enter fullscreen mode Exit fullscreen mode

three, open source address and function use 

address of central warehouse 

in order to make it better for everyone to use, it has been submitted to the central warehouse so that everyone can use it remotely and directly.

https://ohpm.openharmony.cn/#/cn/detail/@abner%2Ftrack 

quick Use 

method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. 

Suggestion: Execute the command under the module path used.

 

ohpm install @abner/track
Enter fullscreen mode Exit fullscreen mode

Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example is as follows:

 

"dependencies": { "@abner/track": "^1.0.0"}
Enter fullscreen mode Exit fullscreen mode

related Functions 

1. Ordinary use


 

TrackProgress({
  pointerWidth: 20,
  onLeftProgress: (progress: number) => {
    console.log("===left:" + progress)
  },
  onRightProgress: (progress: number) => {
    console.log("===right:" + progress)
  }
})
Enter fullscreen mode Exit fullscreen mode

2. Obtain progress


 

TrackProgress({
  pointerWidth: 20,
  onLeftProgress: (progress: number) => {
    console.log("===left:" + progress)
  },
  onRightProgress: (progress: number) => {
    console.log("===right:" + progress)
  }
})
Enter fullscreen mode Exit fullscreen mode

3. Change the color


 

TrackProgress({
  pointerWidth: 20,
  leftPointerBgColor: Color.Orange,
  rightPointerBgColor: Color.Orange,
  trackSelectColor: Color.Orange,
  trackBgBorder: { width: 1, color: Color.Orange, radius: 5 },
  onLeftProgress: (progress: number) => {
    console.log("===left:" + progress)
  },
  onRightProgress: (progress: number) => {
    console.log("===right:" + progress)
  }
})
Enter fullscreen mode Exit fullscreen mode

4. Custom slider


 

TrackProgress({
  pointerWidth: 20,
  leftPointerLayout: this.pointerLayout,
  rightPointerLayout: this.pointerLayout,
  onLeftProgress: (progress: number) => {
    console.log("===left:" + progress)
  },
  onRightProgress: (progress: number) => {
    console.log("===right:" + progress)
  }
})
Enter fullscreen mode Exit fullscreen mode

5. Custom track


 

TrackProgress({
  pointerWidth: 20,
  trackLayout: this.trackLayout,
  trackBgLayout: this.trackBgLayout,
  onLeftProgress: (progress: number) => {
    console.log("===left:" + progress)
  },
  onRightProgress: (progress: number) => {
    console.log("===right:" + progress)
  }
})
Enter fullscreen mode Exit fullscreen mode

related Properties 

property type overview
progressWidth  Length  width of the progress bar 
progressHeight  Length  the height of the progress bar defaults to 50 
onLeftProgress  (progress: number) => void  left Slide Progress
onLeftEndProgress  (progress: number) => void  end of left slide progress 
onRightProgress  (progress: number) => void  right Slide Progress 
onRightEndProgress  (progress: number) => void  progress at the end of the Right Slide 
pointerHeight  Length  height of the slider 
trackLayout  (leftProgress: number, rightProgress: number, viewWidth: number) => void  custom Track 
trackBgLayout  () => void  custom track background view 
leftPointerLayout  () => void  left Slider View 
rightPointerLayout () => void  right Slider View 
leftPointerBgColor  ResourceColor  left slider background color 
rightPointerBgColor  ResourceColor  right slider background color 
leftPointerBorder  Length/BorderRadiuses/ LocalizedBorderRadiuses  the fillet degree of the left slider 
rightPointerBorder  Length/BorderRadiuses/ LocalizedBorderRadiuses  right slider fillet degree 
trackBgBorder  BorderOptions  orbital background Border 
trackSelectColor  ResourceColor  swipe to select the background 
trackNormalColor  ResourceColor  swipe unselected background
pointerLineColor  ResourceColor  slider Line Color 
pointerLineWidth  number /string  slider line width 
pointerLineHeight  slider Line Height 
pointerLineCap  LineCapStyle  slider Line Type 

IV. Relevant Summary 

at present, the left slider and the right slider return percentages. In actual development, both sides may be time, so the current sliding time needs to be calculated according to the progress. 

In many editing scenes, there will be multiple clips, such as segmentation, then there will be multiple track clips. In actual requirements, the creation of the entire track also requires dynamic configuration, that is, specific analysis of specific problems.

Top comments (0)