/*
* Copyright 2013, Edmodo, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License.
* You may obtain a copy of the License in the LICENSE file, or at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.edmodo.rangebar;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.TypedValue;
/**
* Represents a thumb in the RangeBar slider. This is the handle for the slider
* that is pressed and slid.
*/
class Thumb {
// Private Constants ///////////////////////////////////////////////////////
// The radius (in dp) of the touchable area around the thumb. We are basing
// this value off of the recommended 48dp Rhythm. See:
// http://developer.android.com/design/style/metrics-grids.html#48dp-rhythm
private static final float MINIMUM_TARGET_RADIUS_DP = 24;
// Sets the default values for radius, normal, pressed if circle is to be
// drawn but no value is given.
private static final float DEFAULT_THUMB_RADIUS_DP = 14;
// Corresponds to android.R.color.holo_blue_light.
private static final int DEFAULT_THUMB_COLOR_NORMAL = 0xff33b5e5;
private static final int DEFAULT_THUMB_COLOR_PRESSED = 0xff33b5e5;
// Member Variables ////////////////////////////////////////////////////////
// Radius (in pixels) of the touch area of the thumb.
private final float mTargetRadiusPx;
// The normal and pressed images to display for the thumbs.
private final Bitmap mImageNormal;
private final Bitmap mImagePressed;
// Variables to store half the width/height for easier calculation.
private final float mHalfWidthNormal;
private final float mHalfHeightNormal;
private final float mHalfWidthPressed;
private final float mHalfHeightPressed;
// Indicates whether this thumb is currently pressed and active.
private boolean mIsPressed = false;
// The y-position of the thumb in the parent view. This should not change.
private final float mY;
// The current x-position of the thumb in the parent view.
private float mX;
// mPaint to draw the thumbs if attributes are selected
private Paint mPaintNormal;
private Paint mPaintPressed;
// Radius of the new thumb if selected
private float mThumbRadiusPx;
// Toggle to select bitmap thumbImage or not
private boolean mUseBitmap;
// Colors of the thumbs if they are to be drawn
private int mThumbColorNormal;
private int mThumbColorPressed;
// Constructors ////////////////////////////////////////////////////////////
Thumb(Context ctx,
float y,
int thumbColorNormal,
int thumbColorPressed,
float thumbRadiusDP,
int thumbImageNormal,
int thumbImagePressed) {
final Resources res = ctx.getResources();
mImageNormal = BitmapFactory.decodeResource(res, thumbImageNormal);
mImagePressed = BitmapFactory.decodeResource(res, thumbImagePressed);
// If any of the attributes are set, toggle bitmap off
if (thumbRadiusDP == -1 && thumbColorNormal == -1 && thumbColorPressed == -1) {
mUseBitmap = true;
} else {
mUseBitmap = false;
// If one of the attributes are set, but the others aren't, set the
// attributes to default
if (thumbRadiusDP == -1)
mThumbRadiusPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
DEFAULT_THUMB_RADIUS_DP,
res.getDisplayMetrics());
else
mThumbRadiusPx = /*TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
thumbRadiusDP,
res.getDisplayMetrics());*/thumbRadiusDP;
if (thumbColorNormal == -1)
mThumbColorNormal = DEFAULT_THUMB_COLOR_NORMAL;
else
mThumbColorNormal = thumbColorNormal;
if (thumbColorPressed == -1)
mThumbColorPressed = DEFAULT_THUMB_COLOR_PRESSED;
else
mThumbColorPressed = thumbColorPressed;
// Creates the paint and sets the Paint values
mPaintNormal = new Paint();
mPaintNormal.setColor(mThumbColorNormal);
mPaintNormal.setAntiAlias(true);
mPaintPressed = new Paint();
mPaintPressed.setColor(mThumbColorPressed);
mPaintPressed.setAntiAlias(true);
}
// Sets the minimum touchable area, but allows it to expand based on
// image size
int targetRadius = (int) Math.max(MINIMUM_TARGET_RADIUS_DP, thumbRadiusDP);
mTargetRadiusPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
targetRadius,
res.getDisplayMetrics());
if(!mUseBitmap)
{
mHalfWidthNormal = mHalfWidthPressed = mHalfHeightPressed = mHalfHeightNormal= mTargetRadiusPx;
}
else{
mHalfWidthNormal = mImageNormal.getWidth() / 2f;
mHalfHeightNormal = mImageNormal.getHeight() / 2f;
mHalfWidthPressed = mImagePressed.getWidth() / 2f;
mHalfHeightPressed = mImagePressed.getHeight() / 2f;
}
mX = mHalfWidthNormal;
mY = y;
}
// Package-Private Methods /////////////////////////////////////////////////
float getHalfWidth() {
return mHalfWidthNormal;
}
float getHalfHeight() {
return mHalfHeightNormal;
}
void setX(float x) {
mX = x;
}
float getX() {
return mX;
}
boolean isPressed() {
return mIsPressed;
}
void press() {
mIsPressed = true;
}
void release() {
mIsPressed = false;
}
/**
* Determines if the input coordinate is close enough to this thumb to
* consider it a press.
*
* @param x the x-coordinate of the user touch
* @param y the y-coordinate of the user touch
* @return true if the coordinates are within this thumb's target area;
* false otherwise
*/
boolean isInTargetZone(float x, float y) {
if (Math.abs(x - mX) <= mTargetRadiusPx && Math.abs(y - mY) <= mTargetRadiusPx) {
return true;
}
return false;
}
/**
* Draws this thumb on the provided canvas.
*
* @param canvas Canvas to draw on; should be the Canvas passed into {#link
* View#onDraw()}
*/
void draw(Canvas canvas) {
// If a bitmap is to be printed. Determined by thumbRadius attribute.
if (mUseBitmap) {
final Bitmap bitmap = (mIsPressed) ? mImagePressed : mImageNormal;
if (mIsPressed) {
final float topPressed = mY - mHalfHeightPressed;
final float leftPressed = mX - mHalfWidthPressed;
canvas.drawBitmap(bitmap, leftPressed, topPressed, null);
} else {
final float topNormal = mY - mHalfHeightNormal;
final float leftNormal = mX - mHalfWidthNormal;
canvas.drawBitmap(bitmap, leftNormal, topNormal, null);
}
} else {
// Otherwise use a circle to display.
if (mIsPressed)
canvas.drawCircle(mX, mY, mThumbRadiusPx, mPaintPressed);
else
canvas.drawCircle(mX, mY, mThumbRadiusPx, mPaintNormal);
}
}
}