PostHole
Compose Login
You are browsing eu.zone1 in read-only mode. Log in to participate.
rss-bridge 2019-02-08T16:21:47+00:00

Creating a custom video SeekBar on Android

Don’t reinvent the wheel when you don’t need to! Re-use what you can. This post is an overview on creating a custom video SeekBar on Android.


Header Photo by Jakob Owens on Unsplash


A new feature we’ve been building out required the use of a thumbnail picker for video files. After looking around for open-source implementations, it was clear that there wasn’t something that already existed which would fit in with our app – for this reason we needed to build our own video thumbnail picker component. This component, Thumby, can be found over on GitHub.

In this article I want to dive into the iteration of this process, from reusing existing framework classes to building our own open-source solution.


The requirements

When it comes to the selection of a thumbnail for a video, there were a couple of different requirements that we needed to bear in mind for the implementation:

  • Open Thumbnail selection screen, passing Uri for chosen video
  • Load a collection of thumbnails to the SeekBar as a background
  • Load the current thumbnail into the SeekBar thumb background
  • Update the SeekBar thumb background as the user scrubs through the video
  • When chosen, finish the activity and pass the thumbnail location for retrieval

The SeekBar style component that we required in itself doesn’t come across as too complex, overall it would end up consisting of two core parts which were the video timeline (a background essentially made up of thumbnails) and a thumb which would be used by the user to scrub through the selected video:

Customising the Android SeekBar

I wanted to begin by attempting to customise the SeekBar widget from the Android framework – if we could use and tweak an existing implementation, then why recreate the wheel? We didn’t end up going with this approach as it didn’t turn out as great as I had hoped, but it was worth trying for an initial implementation.

If you’re not familiar with the SeekBar component, it’s a component used to seek through media files – you’ll likely see one within the media player in your device. Within the framework, this component extends from the ProgressBar – the main different being the thumb which is used to perform the seek operation via a touch or key press event. In most cases the SeekBar does what you need it to do – you can sync it with some media source on the screen and then use the listeners of the SeekBar to receive seek position updates and have that reflected within the media source that you’re displaying. Although we’re not going to be displaying seekable media on the screen, we do need the functionality of being able to seek through the length of a media source, which the SeekBar is perfect for.

Whilst we can check that functionality off of our list, we don’t actually need to show the SeekBar on the screen. Because it extends from the ProgressBar component we are displayed a determinate progress bar – this bar fills its progress as we seek. Whilst this is great for situations where you are actually seeking through media and require that form of progress indicator, we are not actually playing the media source here so do not require the ProgressBar to be displayed.

progressDrawable = ColorDrawable(ContextCompat.getColor(context, android.R.color.transparent))
background = ColorDrawable(ContextCompat.getColor(context, android.R.color.transparent))
thumb = BitmapDrawable(resources, addWhiteBorderToBitmap(bitmap, 4))

The only issue with this is an offset which is automatically applied to the thumb. This offset exists so that the drawable is always placed centrally on the thumb, so not to interfere with any scrub positioning. By default this is set to the width of the thumb / 2 – whilst in most cases this is fine, if you are showing a video timeline underneath the SeekBar then this may cause some issues. If this is the case then you may need to assign some padding to each side of the SeekBar to ensure that your thumb aligns correctly with the background that it’s showing on-top of.

With all of the above in place, this implementation mostly worked. We had our video timeline that showed a sliding thumb for the selected thumbnail at the current seek position. Whilst this worked, there were some issues with performance – and this solution isn’t very scalable. For example:

  • With this approach you need the thumbnails pre-loaded so that they can be accessed by the thumbnail view within the SeekBar. Whilst you can fetch video thumbnails from the media store, hitting this every single time the SeekBar progress changes isn’t very efficient and will cause some lag in your layout.
  • With the above in mind you also become a bit restricted when it comes to larger videos. For example, if the user loads in a video that is 8 minutes long you’re going to still want to show a regularly updated thumbnail on the SeekBar – otherwise it will appear as though the thumbnail isn’t changing. Without hitting the MediaStore for thumbnails every second within the progress, you’d have to keep a reference to all these thumbnails. And if you didn’t want to load them all upfront like that, then loading them on the fly in chunks would be a bit fiddly – what if the user skipped straight to 75% of the progress, and then back to 50%? There are a few situations that make that idea a bit complicated.

Due to these restrictions, we decided that customising the SeekBar component wasn’t going to work for what we wanted. Whilst this didn’t work out, this didn’t take long at all to try out and extending from existing components is always favourable, as if done properly you avoid re-inventing the wheel and at the end the implementations will likely be easier to maintain for you and other developers.

Creating a custom implementation

Because of the things mentioned above, we needed to put a custom seekbar solution in place for the our thumbnail selection. Now, the video timeline display worked fine from the previous implementation so we kept that – the only thing that needed to be changed was the seekbar with the dynamic preview.

[...]


Original source

Reply