-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gesture controls #1604
Gesture controls #1604
Conversation
Thanks for the pull request, looks good!
Yep, that's right, there's even a |
100 | ||
); | ||
if (brightnessNormalized < 25) { | ||
playerImpl.getBrightnessImageView().setImageDrawable( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crash in old versions of Android.
A very simple solution, thankfully: use AppCompatResources.getDrawable
instead.
I was also worried about performance, but it seems to be cached, both the Android and compat library versions, so it's all good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that - AS stopped complaining when I used it through getResources(), but yeah, I didn't check it manually...
* @param to final progress value after animation | ||
* @param duration how long the animation will take, in milliseconds | ||
*/ | ||
public static void animateProgressBar(ProgressBar progressBar, int to, long duration) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this function below the others, but on top of the Internals
block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll do
@mauriciocolli Design seemed like a biggest problem, but while tinkering with it, I thought about implementing some sort of speed-based behavior, so that user can change values more precisely by moving finger slowly. May try it, as well as maybe introduce some "fake" state of progress bar that rounds to the closest value after gesture, instead of that choppy movement. |
@mauriciocolli While talking about gesture controls, there's one more thing that doesn't feel right - when using fast rewind controls, bright background may make icons barely visible: E.g. YT web player solves this problem with dark circle as a background: The other thing we could do is temporarily dim the background (as with play/pause), but then rewind would still be in conflict with play button. |
4896b40
to
4db6004
Compare
Wow - it seems like GestureDetector's and GestureDetectorCompat's onScroll gets called differently. Luckily, Compat version seems to be more sensitive (it works with slow movement). After a lot of testing, to me the best solution seems to use event's distance directly as a value for progress incrementation and set max progress value based on screen size. Speed seems to be inconsistent and attempts to "normalize" value before use by e.g division or log result in number rounded down to zero when doing small movements. I could maybe solve this by some overcomplicated solution I didn't think of or by skipping every Nth event and using progress animation again, but I don't think it would give us any advantage. Maybe if drawing on screen was too expensive, but actually, number of total motion events (including historical) should be <= touchscreen scan rate, which will probably match framerate (I've counted <= 60 per second on my device with At the end, we can think of space used for gesture as an invisible seekbar, which is predictable, precise and smooth solution at the same time (and allows us to get from 0% to 100% at one long swipe). Value from it gets converted to nearest volume/brightness level and applied. (Edit: sorry for force push - I've corrected typo in one commit message) |
IMO it doesn't matter much, the user is focused on the video and will certainly notice the rewind/fast forward. Though I don't mind if you want to make more visible, feel free to do it (of course, in a way that doesn't draw too much attention). And the fact that the icons stay very shortly in screen (video is already loaded) makes the player seems snappy, though the "artifacts" (progress bar visible in a split second, for example) can be seen as a buggy player UI to the user. The optimal solution would be to keep the short animation and fix them.
Exactly, I like this implementation, works and feels much better. Oh, and if you don't mind, please, when this PR is ready remove the commits that cancel each other. |
private int maxGestureLength; | ||
|
||
{ | ||
DisplayMetrics m = getResources().getDisplayMetrics(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of using the rootView
's width and height?
The code would be simpler, and using this approach, we could already support the multi window mode just by adding a listener to the rootView
layout changes, that when we detect one, we could simply update the variable and the gesture would work correctly in the new size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, will do.
|
||
private final int MOVEMENT_THRESHOLD = 40; | ||
private final int eventsThreshold = 8; | ||
private boolean triggered = false; | ||
private int eventsNum; | ||
|
||
// TODO: Improve video gesture controls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove this TODO
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great :D
Just a simple background similar to YT or those new gesture controls to make it consistent.
Otherwise it's fine, I was just interested in "visibility". Frankly, any sort of long animation or effects would just get in the way of users while watching. Oh, one more thing - #1603 (3. point) and #1199 - those raster images look terrible when scaling, but that's thing for separate PR. |
6e35b29
to
a2456cb
Compare
Okay, cleaned up history - commits changing gesture control are squashed into one big (newer ones were just fixes anyway). Oh, and changed threshold check to not block detection while moving and added check for vertical movement - now there's no stuttering when moving through starting location and user will not trigger gesture when e.g. cleaning display :D Checked both code and running app, everything seems fine. |
@@ -424,6 +440,20 @@ public void initViews(View rootView) { | |||
titleTextView.setSelected(true); | |||
channelTextView.setSelected(true); | |||
|
|||
getRootView().addOnLayoutChangeListener((view, l, t, r, b, ol, ot, or, ob) -> { | |||
// Use smaller value to be consistent between screen orientations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Little thing that's bothering the micro-optimization part of me, we could return if the size itself didn't changed:
if (left == oldLeft && right == oldRight &&
top == oldTop && bottom == oldBottom){
return;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about if (l != ol || t != ot || r != or || b != ob) { // do things... }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine, this piece of code is short enough to be a good a choice.
a2456cb
to
e936640
Compare
Added check to max length updates - I should be ready for merging. |
// Use smaller value to be consistent between screen orientations | ||
// (and to make usage easier) | ||
int width = r - l, height = b - t; | ||
maxGestureLength = (int) ((width > height ? width : height) * MAX_GESTURE_LENGTH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this check inverted?
And while you fix this, take the opportunity and move this to the initListeners
function, I think it makes more sense there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, now I've got it, sorry...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just throw a Math.min(width, height)
in there, even easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better idea, thanks.
if (DEBUG) Log.d(TAG, "onScroll().brightnessControl, currentBrightness = " + currentProgressPercent); | ||
|
||
if (currentProgressPercent < 0.25) { | ||
playerImpl.getBrightnessImageView().setImageDrawable( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could improve readability and be less redundant here (and above) introducing a variable:
// We could initialize at the "else" value, but I think
// this way makes it more readable.
final int iconRes;
if (currentProgressPercent < 0.25) {
iconRes = R.drawable.ic_brightness_low_white_72dp;
} else if (currentProgressPercent < 0.75) {
iconRes = R.drawable.ic_brightness_medium_white_72dp;
} else {
iconRes = R.drawable.ic_brightness_high_white_72dp;
}
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a bad idea, will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, ternary operator is right-associative... :
playerImpl.getVolumeImageView().setImageDrawable(
AppCompatResources.getDrawable(getApplicationContext(),
currentProgressPercent <= 0
? R.drawable.ic_volume_off_white_72dp
: currentProgressPercent < 0.25
? R.drawable.ic_volume_mute_white_72dp
: currentProgressPercent < 0.75
? R.drawable.ic_volume_down_white_72dp
: R.drawable.ic_volume_up_white_72dp
)
);
Can I use this? :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely hard to read, but if you keep the condition result in the same line, yeah. A variable here can help it again to keep the line shorter and the style closer to what is used currently:
final int resId = currentProgressPercent <= 0 ? R.drawable.ic_volume_off_white_72dp
: currentProgressPercent < 0.25 ? R.drawable.ic_volume_mute_white_72dp
: currentProgressPercent < 0.75 ? R.drawable.ic_volume_down_white_72dp
: R.drawable.ic_volume_up_white_72dp;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just wanted to avoid additional variable... but okay, will do.
e936640
to
711ff43
Compare
Fixed listener and res selection. |
-Previous version used emojis for brightness and volume icons, which may be inconsistent across devices and do not fit well with other parts of UI (Frankly, previous version was more informative than eye-candy) -This commit replaces old version with circular progress bar that shows current value (before conversion). Gesture mode (volume/brightness) is indicated by icon that changes between (4/3) modes according to current value -Text information about current value was removed, because with progress bar present it does not add any real value to UI.
-White icon was barely visible on bright backgrounds -Secondly, drawable is set programmatically anyway and so it's setting in XML is good just for a confusion
fe46574
to
a469086
Compare
@mauriciocolli Great! Thanks for your help (and patience) :) |
Current gesture controls work but look like an afterthought. This PR introduces circular design with progress bar and material icons that changes depending on current value.
Demo:
Changed version seems to work without any problems.