From 6cff54c18f1fd5966ce305331dd356dee816001c Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Sat, 28 Dec 2013 21:25:00 -0800 Subject: [PATCH] UI tweaks for keyboard Maximum scroll and zoom range for the keyboard and strip, some style changes to the knob views (to make them work better for light theme and also scale for density). This version is basically at least as good as the old view (although is still lacking octave buttons). --- android/res/layout/piano2.xml | 4 +- .../android/ui/PianoActivity2.java | 2 +- .../widgets/keyboard/KeyboardView.java | 9 ++- .../widgets/keyboard/ScrollStripView.java | 69 +++++-------------- .../android/widgets/knob/KnobView.java | 11 +-- 5 files changed, 35 insertions(+), 60 deletions(-) diff --git a/android/res/layout/piano2.xml b/android/res/layout/piano2.xml index 65b412f..a0841bc 100644 --- a/android/res/layout/piano2.xml +++ b/android/res/layout/piano2.xml @@ -88,8 +88,8 @@ > diff --git a/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java b/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java index b9dadfa..7160142 100644 --- a/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java +++ b/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java @@ -66,7 +66,7 @@ public class PianoActivity2 extends Activity { //piano_ = (PianoView)findViewById(R.id.piano); keyboard_ = (KeyboardView)findViewById(R.id.piano); - keyboard_.setKeyboardSpec(KeyboardSpec.make3Layer()); + keyboard_.setKeyboardSpec(KeyboardSpec.make2Layer()); ScrollStripView scrollStrip_ = (ScrollStripView)findViewById(R.id.scrollstrip); scrollStrip_.bindKeyboard(keyboard_); cutoffKnob_ = (KnobView)findViewById(R.id.cutoffKnob); diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java b/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java index 6946bff..97ec3d7 100644 --- a/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java +++ b/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java @@ -32,8 +32,8 @@ import com.levien.synthesizer.core.midi.MidiListener; public class KeyboardView extends View { public KeyboardView(Context context, AttributeSet attrs) { super(context, attrs); - nKeys_ = 108; // TODO: make configurable - firstKey_ = 0; + nKeys_ = 96; + firstKey_ = 12; noteStatus_ = new byte[128]; noteForFinger_ = new int[FINGERS]; for (int i = 0; i < FINGERS; i++) { @@ -77,6 +77,11 @@ public class KeyboardView extends View { invalidate(); } + public float getMaxScroll() { + float width = drawingRect_.width(); + return (zoom_ - 1) * width; + } + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java b/android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java index 0564e63..6a5a8f2 100644 --- a/android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java +++ b/android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java @@ -18,6 +18,7 @@ package com.levien.synthesizer.android.widgets.keyboard; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; @@ -29,10 +30,13 @@ public class ScrollStripView extends View { super(context, attrs); drawingRect_ = new Rect(); paint_ = new Paint(); + paint_.setAntiAlias(true); + paint_.setStyle(Paint.Style.FILL); + paint_.setColor(Color.GRAY); touchDown_ = new boolean[2]; touchx_ = new float[2]; offset_ = -2000.0f; // TODO: make more systematic - zoom_ = 3.0f; + zoom_ = 2.5f; } public void bindKeyboard(KeyboardView kv) { @@ -43,12 +47,16 @@ public class ScrollStripView extends View { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); + float density = getResources().getDisplayMetrics().density; getDrawingRect(drawingRect_); - float x0 = 100f + offset_; - float x1 = x0 + 100f * zoom_; - paint_.setStyle(Paint.Style.STROKE); - canvas.drawLine(x0, drawingRect_.top, x0, drawingRect_.bottom, paint_); - canvas.drawLine(x1, drawingRect_.top, x1, drawingRect_.bottom, paint_); + float y = drawingRect_.centerY(); + float spacing = 10f * density * zoom_; + int min = -(int)(offset_ / spacing); + int max = -(int)((offset_ - drawingRect_.width()) / spacing) + 1; + for (int i = min; i <= max; i++) { + float x = offset_ + i * 10f * density * zoom_; + canvas.drawCircle(x, y, 3.0f * density, paint_); + } } private boolean onTouchDown(int id, float x) { @@ -117,11 +125,14 @@ public class ScrollStripView extends View { redraw = true; } else if (touchDown_[0] && touchDown_[1]) { zoom_ = scaleAtTouch_ * (touchx_[1] - touchx_[0]); + // TODO: min and max zoom values maybe should depend on screen size + zoom_ = Math.max(1.0f, zoom_); + zoom_ = Math.min(4.0f, zoom_); offset_ = touchx_[0] + zoom_ / zoomAtTouch_ * deltaAtTouch_; redraw = true; } + offset_ = Math.max(-keyboardView_.getMaxScroll(), offset_); offset_ = Math.min(0, offset_); - // TODO: max offset } if (redraw) { if (keyboardView_ != null) { @@ -132,50 +143,6 @@ public class ScrollStripView extends View { return true; } - /** - * Layout measurement for this widget. - * This method just sets a basic minimum size and makes the widget maximized otherwise. - */ - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - int width = 0; - int height = 0; - - float density = getResources().getDisplayMetrics().density; - int maxHeight = (int) (50.0f * density + 0.5f); - - switch (widthMode) { - case MeasureSpec.EXACTLY: - width = widthSize; - break; - case MeasureSpec.AT_MOST: - width = widthSize; - break; - case MeasureSpec.UNSPECIFIED: - width = 10; - break; - } - - switch (heightMode) { - case MeasureSpec.EXACTLY: - height = heightSize; - break; - case MeasureSpec.AT_MOST: - height = Math.min(maxHeight, heightSize); - break; - case MeasureSpec.UNSPECIFIED: - height = 10; - break; - } - - setMeasuredDimension(width, height); - } - Rect drawingRect_; Paint paint_; float offset_; diff --git a/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java b/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java index 2b4d469..50397a8 100644 --- a/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java +++ b/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java @@ -60,6 +60,7 @@ public class KnobView extends View { knobPaint_.setColor(Color.WHITE); float density = getResources().getDisplayMetrics().density; knobPaint_.setStrokeWidth(2.0f * density); + arcWidth_ = 8.0f * density; rect_ = new Rect(); rectF_ = new RectF(); textRect_ = new Rect(); @@ -264,18 +265,18 @@ public class KnobView extends View { // Draw indicator. knobPaint_.setShader(null); - knobPaint_.setColor(Color.WHITE); + knobPaint_.setColor(Color.BLACK); knobPaint_.setStyle(Style.STROKE); - final float arcWidth = 15.0f; canvas.drawArc(rectF_, - (float)(knobValue_ * 360 * 0.8 + 90 - arcWidth / 2 + 36), - (float)arcWidth, + (float)(knobValue_ * 360 * 0.8 + 90 - arcWidth_ / 2 + 36), + (float)arcWidth_, false, knobPaint_); // Draw text. String knobValueString = String.format("%.2f", getValue()); Typeface typeface = Typeface.DEFAULT_BOLD; + knobPaint_.setColor(Color.WHITE); knobPaint_.setTypeface(typeface); knobPaint_.setTextAlign(Align.CENTER); knobPaint_.setTextSize(rectF_.width() / 8); @@ -379,6 +380,8 @@ public class KnobView extends View { private RadialGradient radialGradient_; private RadialGradient innerRadialGradient_; + private float arcWidth_; + // Position of the finger relative to the knob. private double previousX_ = 0; private double previousY_ = 0;