Skip to content

Instantly share code, notes, and snippets.

@un1tz3r0
Created July 8, 2016 03:36
Show Gist options
  • Save un1tz3r0/598f1ed64eadc017d2930ad0fdc2ef11 to your computer and use it in GitHub Desktop.
Save un1tz3r0/598f1ed64eadc017d2930ad0fdc2ef11 to your computer and use it in GitHub Desktop.
A work in progress based on the API Examples LabelView.java custom view, which implements (partially) a custom control similar to SeekBar,
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License 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.example.android.apis.view;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import android.animation.*;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.graphics.drawable.shapes.*;
import android.util.*;
import android.view.*;
import android.view.GestureDetector.*;
import android.widget.*;
import com.example.android.apis.*;
import android.app.*;
import java.util.*;
import android.view.animation.*;
/**
TODO: Major cleanup, some refactoring. This working draft is a mess.
TODO: Add missing getters and setters, and make sure all setters that should call invalidate do so.
TODO: Add event hooks for subclasses to respond to various changes to the objects state.
TODO: Add mising styleable attribute definitions for exposed properties.
TODO: Implement a better more cohesive physics model and animations.
TODO: Finish handling of tickmarks and add textual labels and value feedback that follows the thumb.
Implement collapsing tickmark labels based on multiple priority levels and available real estate.
TODO: Implement themed appearance for default drawing style.
-- V.C.
*/
/** --------------------------------------------
in res/values/attrs.xml...
<resources>
...
<declare-styleable name="LabelView">
<attr name="text" format="string" />
<attr name="ticks" format="string" />
<attr name="minVal" format="float" />
<attr name="maxVal" format="float" />
<attr name="textColor" format="color" />
<attr name="barColor" format="color" />
<attr name="tickColor" format="color" />
<attr name="textSize" format="dimension" />
<attr name="barThickness" format="dimension" />
<attr name="barPadding" format="dimension" />
<attr name="tickHeight" format="dimension" />
...
</declare-styleable>
...
</resources>
-------------------------------------------- */
/**
* Example of how to write a custom subclass of View. LabelView
* is used to draw simple text views. Note that it does not handle
* styled text or right-to-left writing systems.
*
*/
public class LabelView extends View
{
// these determine the rate at which the thumb is animated to follow the pointer
// during touch interaction... mDragAnimateDuration is how long the thumb will take
// to get from its current position to the pointer, which is restarted each time the
// gesturedetector reports motion as part of a scrolling gesture. mSnapAnimateDuration
// is how long it should take the thumb to animate jumping from its resting value to the
// initial touch event location (i.e. when tracking begins, within onDown() vs. onScroll().)
private int mDragAnimateDuration = 250;
private int mSnapAnimateDuration = 125;
private float mFlingVelocityDenominator = 4f;
/*
private float mScrollFriction = 0.5f;
private float mScrollMomentum = 0.2f;
private class Smoother
{
int mMin, mMax, mValue, mFinal, mVel, mFriction;
};
*/
private Paint mTextPaint;
private String mText;
private int mAscent;
private ArraySet<Float> mTicks = new ArraySet<>();
// the bounded value which is linked to the thumb position
private float mValue = 0.5f, mMinVal = 0f, mMaxVal = 1f;
private boolean mIsTracking = false;
// appearance and geometry of the bar along which the thumb moves
private Paint mBarPaint;
private float mBarPadding = 9;
private float mBarThickness = 3;
// the geometry of the ticks below the slider
private Paint mTickPaint;
private float mTickHeight = 12;
private float mTickPadding = -6;
private float mTickThickness = 2;
// these only have an effect if the default thumb drawable is in use
private int mDotActiveColor;
private int mDotColor;
// the current thumb drawable, and whether or not it is the default StateListDrawable of PathShape ShapeDrawables
private Drawable mDotDrawable;
private boolean mIsDefaultDotDrawable;
// all of the stuff we need for smoothly animated touch interaction for our thumb
private OnGestureListener mOnGestureListener;
private GestureDetector mGestureDetector;
private Scroller mScroller;
private ValueAnimator mScrollAnimator;
private ValueAnimator mGlowAnimator;
private float mThumbGlowRadius;
private float mThumbWidth;
private float mThumbHeight;
private int mThumbCornerRadius;
private long mGlowAnimateDuration;
/**
* Constructor. This version is only needed if you will be instantiating
* the object manually (not from a layout XML file).
* @param context
*/
public LabelView(Context context)
{
super(context);
initLabelView();
}
/**
* Construct object, initializing with any attributes we understand from a
* layout file. These attributes are defined in
* SDK/assets/res/any/classes.xml.
*
* @see android.view.View#View(android.content.Context, android.util.AttributeSet)
*/
public LabelView(Context context, AttributeSet attrs)
{
super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequence s = a.getString(R.styleable.LabelView_text);
if (s != null)
setText(s.toString());
// Retrieve the color(s) to be used for this view and apply them.
// Note, if you only care about supporting a single color, that you
// can instead call a.getColor() and pass that to setTextColor().
setTextColor(a.getColor(R.styleable.LabelView_textColor, getResources().getColor(android.R.color.primary_text_dark)));
int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
if(textSize > 0)
setTextSize(textSize);
setBarColor(a.getColor(R.styleable.LabelView_barColor, getResources().getColor(android.R.color.secondary_text_dark)));
setBarThickness(a.getDimensionPixelOffset(R.styleable.LabelView_barThickness, 3));
setBarPadding(a.getDimensionPixelOffset(R.styleable.LabelView_barPadding, 6));
setTickColor(a.getColor(R.styleable.LabelView_tickColor, getResources().getColor(android.R.color.tertiary_text_dark)));
setTickPadding(a.getDimensionPixelOffset(R.styleable.LabelView_tickPadding, 3));
setTickHeight(a.getDimensionPixelOffset(R.styleable.LabelView_tickHeight, 6));
setTickThickness(a.getDimensionPixelOffset(R.styleable.LabelView_tickThickness, 2));
setDotColor(a.getColor(R.styleable.LabelView_dotColor, getResources().getColor(android.R.color.holo_blue_dark)));
setDotActiveColor(a.getColor(R.styleable.LabelView_dotActiveColor, getResources().getColor(android.R.color.holo_blue_light)));
Drawable dotDrawable = a.getDrawable(R.styleable.LabelView_dotDrawable);
if(dotDrawable != null)
setDotDrawable(dotDrawable);
else
setDefaultDotDrawable();
a.recycle();
}
public void onStopMoving()
{
// TODO: Implement this method
}
private final void initLabelView()
{
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mBarPaint = new Paint();
mBarPaint.setAntiAlias(true);
mBarPaint.setStrokeCap(Paint.Cap.ROUND);
mBarPaint.setStrokeWidth(mBarThickness * getResources().getDisplayMetrics().density);
mBarPaint.setColor(android.R.color.tertiary_text_dark);
mTickPaint = new Paint();
mTickPaint.setAntiAlias(true);
mTickPaint.setStrokeCap(Paint.Cap.ROUND);
mTickPaint.setStrokeWidth(mTickThickness * getResources().getDisplayMetrics().density);
mTickPaint.setColor(android.R.color.secondary_text_dark);
// Must manually scale the desired text size to match screen density
mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
mTextPaint.setColor(android.R.color.primary_text_dark);
setPadding(3, 3, 3, 3);
mDotColor = getResources().getColor(android.R.color.holo_blue_light);
mDotActiveColor = getResources().getColor(android.R.color.holo_blue_bright);
mThumbHeight = 17;
mThumbWidth = 12;
mThumbGlowRadius = 3;
mThumbCornerRadius = 2;
mGlowAnimateDuration = 125;
setDefaultDotDrawable();
calcMetrics();
// set up scroller and value animator for smooooove moooves
mScroller = new Scroller(getContext(), null, true);
mScrollAnimator = ValueAnimator.ofFloat(0f,1f);
mScroller.setFriction(0.1f);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mScroller.computeScrollOffset();
mValue = getValueAtX(mScroller.getCurrX());
postInvalidate();
if (mScroller.isFinished()) {
mScrollAnimator.cancel();
if(mIsTracking==false)
LabelView.this.onStopMoving();
}
}
});
// set up gesture detection for touch interaction
mOnGestureListener = new OnGestureListener() {
@Override
public boolean onDown(MotionEvent pos)
{
mIsTracking = true;
mScroller.forceFinished(true);
mScroller.startScroll(Math.round(getXAtValue(getValue())), 0, Math.round(pos.getX() - getXAtValue(getValue())), 0, mSnapAnimateDuration);
mScrollAnimator.start();
// TODO: Implement this method
//mGlowAnimator.cancel();
//mGlowAnimator.setCurrentFraction(0f);
//mGlowAnimator.start();
onStartTracking();
return true;
}
@Override
public void onShowPress(MotionEvent p1)
{
// TODO: Implement this method
}
@Override
public boolean onSingleTapUp(MotionEvent p1)
{
// TODO: Implement this method
return false;
}
@Override
public boolean onScroll(MotionEvent first, MotionEvent last, float dx, float dy)
{
//if(mWasFling)"
// return false;
if(mScroller.isFinished())
{
mScrollAnimator.cancel();
mScroller.startScroll(Math.round(getXAtValue(getValue())), 0, Math.round(last.getX()-getXAtValue(getValue())), 0, mDragAnimateDuration);
mScrollAnimator.start();
}
else
{
mScrollAnimator.cancel();
mScroller.extendDuration(mDragAnimateDuration);
mScroller.setFinalX(Math.round(last.getX()));
mScrollAnimator.start();
}
return true;
}
@Override
public void onLongPress(MotionEvent p1)
{
// TODO: Implement this method
}
@Override
public boolean onFling(MotionEvent p1, MotionEvent p2, float p3, float p4)
{
//mWasFling = true;
// TODO: Implement this method
mScrollAnimator.cancel();
mScroller.forceFinished(true);
mScroller.fling(Math.round(getXAtValue(getValue())), 0, Math.round(p3/mFlingVelocityDenominator + (1f-1f/mFlingVelocityDenominator)*mScroller.getCurrVelocity()*0f), 0, Math.round(mMetrics.bxl), Math.round(mMetrics.bxr), 0, 0);
mScrollAnimator.start();
return true;
}
};
mGestureDetector = new GestureDetector(getContext(), mOnGestureListener);
// stuff for animating glow effect while tracking thumb
// ... is already set up by setDefaultDotDrawable()
}
public static int[] stateSetOps(int[] in, int[] exclude, int[] include, boolean reverseOrder)
{
// use an ArraySet internally to hold the resulting set while we iteratively build it up
ArraySet<Integer> set = new ArraySet<>(in.length + include.length);
// iterate over each element of in[] since the resulting set is always a subset or its identity
for(int i = 0; i < in.length; i++)
{
boolean found = false;
// check if in[i] is last occurrence in in[] and short circuit if we find out otherwise
for(int k = i + 1; k < in.length && !found; k++)
if(in[i] == in[k])
found = true;
// check if in[i] occurs in exclude[], and short circuit if found
for(int j = 0; j < exclude.length && !found; j ++)
if(in[i] == exclude[j])
found = true;
// if both above searches fail to match anything then in[i] is a member of the resulting set
if(!found)
set.add(i);
}
for(int l = 0; l < include.length; l ++)
{
boolean found = false;
// check if include[i] is last occurrence in include[] and short circuit if we find out otherwise
for(int k = l + 1; k < include.length && !found; k++)
if(include[l] == include[k])
found = true;
if(found)
continue;
// we reach this point once for each unique element of include[]...
boolean found_in = false;
boolean found_exclude = false;
for (int m = 0; m < in.length && !found_in; m++)
if (include[l] == in[m])
found_in = true;
// in the case of include-then-exclude (reverseOrder is true), if in[] contains include[l] then we never need to add it to result set, can skip searching for include[l] in exclude[]
// in the case of exclude-then-include (reverseOrder is false), if in[] does not contain include[l], then we always need to add it to result set, can skip searching for include[l] in exclude[]
if((reverseOrder && !found_in) || (!reverseOrder && found_in))
// check if include[i] occurs in exclude[], and short circuit if found
for(int j = 0; j < exclude.length && !found_exclude; j ++)
if(include[l] == exclude[j])
found_exclude = true;
// if include-then-exclude, include[l] is added to results if it isnt a member of either in[] or exclude[] (meaning it is neither already added to the results, nor to be excluded from them)
// if exclude-then-include, include[l] is added to results unless it is a member of in[] but not of exclude[] (meaning that it was not added because it is not a member of in[] or because it is a member of both in[] and exclude[])
if((reverseOrder && (!found_in && !found_exclude)) ||
(!reverseOrder && (!found_in || found_exclude)))
set.add(include[l]);
}
// allocate a java array and populate it with result set
int[] out = new int[set.size()];
for(int i = 0; i < set.size(); i ++)
out[i] = set.valueAt(i);
// return the new array
return out;
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
if(event.getActionMasked() == MotionEvent.ACTION_DOWN)
{
this.mDotDrawable.setState(stateSetOps(mDotDrawable.getState(), EMPTY_STATE_SET, PRESSED_STATE_SET, false));
mGlowAnimator.cancel();
//mGlowAnimator.setupEndValues();
//mGlowAnimator.end();
mGlowAnimator.start();
mIsTracking = true;
}
boolean gestureHandled = mGestureDetector.onTouchEvent(event);
if(event.getActionMasked() == MotionEvent.ACTION_UP ||
event.getActionMasked() == MotionEvent.ACTION_CANCEL)
{
this.mDotDrawable.setState(stateSetOps(mDotDrawable.getState(), PRESSED_STATE_SET, EMPTY_STATE_SET, false));
this.mGlowAnimator.cancel();
this.mGlowAnimator.reverse();
mIsTracking = false;
}
if(gestureHandled)
return true;
return super.onTouchEvent(event);
}
protected /*abstract*/ void onStartTracking()
{
// mGlowAnimator.start();
}
protected /*abstract*/ void onStopTracking()
{
// TODO: Implement me or dont. Im like, "whateva, man".
}
private void setDefaultDotDrawable()
{
Path dotPath = new Path();
dotPath.moveTo(mThumbGlowRadius, mThumbGlowRadius);
dotPath.lineTo(mThumbGlowRadius+mThumbWidth, mThumbGlowRadius);
dotPath.lineTo(mThumbGlowRadius+mThumbWidth, mThumbGlowRadius+mThumbHeight-mThumbWidth/2f);
dotPath.lineTo(mThumbGlowRadius+mThumbWidth/2f, mThumbGlowRadius+mThumbHeight);
dotPath.lineTo(mThumbGlowRadius, mThumbGlowRadius+mThumbHeight-mThumbWidth/2f);
dotPath.close();
PathShape dotShape = new PathShape(dotPath, Math.round(mThumbGlowRadius*2f+mThumbWidth), Math.round(mThumbGlowRadius*2f+mThumbHeight));
ShapeDrawable dotInactiveDrawable = new ShapeDrawable(dotShape);
dotInactiveDrawable.setIntrinsicWidth(Math.round(mThumbWidth+mThumbGlowRadius*2f));
dotInactiveDrawable.setIntrinsicHeight(Math.round(mThumbHeight +mThumbGlowRadius*2f ));
dotInactiveDrawable.getPaint().setAntiAlias(true);
dotInactiveDrawable.getPaint().setColor(mDotColor);
dotInactiveDrawable.getPaint().setStyle(Paint.Style.FILL);
dotInactiveDrawable.getPaint().setPathEffect(new CornerPathEffect(mThumbCornerRadius));
ShapeDrawable dotActiveDrawable = new ShapeDrawable(dotShape);
dotActiveDrawable.setIntrinsicWidth(Math.round(mThumbWidth+mThumbGlowRadius*2f));
dotActiveDrawable.setIntrinsicHeight(Math.round(mThumbHeight+mThumbGlowRadius*2f));
dotActiveDrawable.getPaint().setAntiAlias(true);
dotActiveDrawable.getPaint().setColor(mDotActiveColor);
dotActiveDrawable.getPaint().setAlpha(0);
dotActiveDrawable.getPaint().setStyle(Paint.Style.FILL);
dotActiveDrawable.getPaint().setMaskFilter(new BlurMaskFilter(mThumbGlowRadius, BlurMaskFilter.Blur.SOLID));
dotActiveDrawable.getPaint().setPathEffect(new CornerPathEffect(mThumbCornerRadius));
LayerDrawable dotDrawable = new LayerDrawable(new Drawable[] {
dotInactiveDrawable,
dotActiveDrawable
});
mGlowAnimator = ObjectAnimator.ofInt(dotActiveDrawable.getPaint(), "alpha", 0, 255);
mGlowAnimator.addUpdateListener(new ObjectAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator p1)
{
postInvalidate();
}
});
mGlowAnimator.setDuration(mGlowAnimateDuration);
mDotDrawable = dotDrawable;
mIsDefaultDotDrawable = true;
}
/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
/**
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY)
{
// We were told how big to be
result = specSize;
}
else
{
// Measure the text
result = (int)(
// mTextPaint.measureText(mText)
+ getPaddingLeft()
+ getPaddingRight() + mMetrics.dw + mTickThickness * 2f + mBarThickness);
if (specMode == MeasureSpec.AT_MOST )
{
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
mAscent = (int) mTextPaint.ascent();
if (specMode == MeasureSpec.EXACTLY)
{
// We were told how big to be
result = specSize;
}
else
{
calcMetrics();
// Measure the text (beware: ascent is a negative number)
result = (int) (-mAscent + mTextPaint.descent()) +
+ getPaddingBottom() + (int)(mMetrics.tkyb + mBarPadding + mTickThickness/2f);
if (specMode == MeasureSpec.AT_MOST)
{
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Render the text
*
* @see android.view.View#onDraw(android.graphics.Canvas)
*/
private static class Metrics
{
float dw, dh, // the width and height of the thumb drawable
dox, doy, // offset of thumb drawable centering it on the origin
bxl, bxr, // the x extents of the bar/thumb travel
by, // the y position of the bar/thumb origin
tkyt, tkyb; // the y extents of the tick marks
}
private final Metrics mMetrics = new Metrics();
private void calcMetrics()
{
// get size and origin of thumb drawable
mMetrics.dw = mDotDrawable.getIntrinsicWidth();
mMetrics.dh = mDotDrawable.getIntrinsicHeight();
mMetrics.dox = mMetrics.dw/-2f;
mMetrics.doy = mMetrics.dw/-2f;
// get horizontal extents and vertical position of the bar
mMetrics.bxl = getPaddingLeft() - mMetrics.dox;
mMetrics.bxr = getWidth() - (getPaddingRight() + mMetrics.dox + mMetrics.dw);
mMetrics.by = getPaddingTop() - mMetrics.doy;// + mBarThickness / 2f;
mMetrics.tkyt = mMetrics.by + mMetrics.doy - mThumbGlowRadius + mMetrics.dh + mTickPadding + mTickThickness / 2f;
mMetrics.tkyb = mMetrics.tkyt + mTickHeight;
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
float ta = mTextPaint.ascent(),
td = mTextPaint.descent(),
th = -ta + td;
// recalculate metrics, and then populate local copies
calcMetrics();
float dw = mMetrics.dw, dh = mMetrics.dh, dox = mMetrics.dox, doy = mMetrics.doy, // get size and origin of thumb drawable
bxl = mMetrics.bxl, bxr = mMetrics.bxr, by = mMetrics.by, // get horizontal extents and vertical position of the bar
tkyt = mMetrics.tkyt, tkyb = mMetrics.tkyb; // and vertical extents of tick marks
ArraySet<Float> ticks = new ArraySet<>();
ticks.addAll(mTicks);
ticks.add(mMinVal);
ticks.add(mMaxVal);
for (Float tick : ticks)
{
float tickq = (tick - mMinVal) / (mMaxVal - mMinVal);
float tickx = tickq * (bxr - bxl) + bxl;
canvas.drawLine(tickx, tkyt, tickx, tkyb, mTickPaint);
}
canvas.drawLine(bxl, by, bxr, by, mBarPaint);
canvas.drawText(mText, getPaddingLeft(), canvas.getHeight() - getPaddingBottom() - td, mTextPaint);
float
dx = dox + bxl + (bxr - bxl) * ((mValue - mMinVal) / (mMaxVal - mMinVal)),
dy = by + doy;
mDotDrawable.setBounds(Math.round(dx), Math.round(dy), Math.round(dx + dw), Math.round(dy + dh));
mDotDrawable.draw(canvas);
}
private Rect getThumbBox()
{
// recalculate metrics, and then populate local copies
calcMetrics();
float dw = mMetrics.dw, dh = mMetrics.dh, dox = mMetrics.dox, doy = mMetrics.doy, // get size and origin of thumb drawable
bxl = mMetrics.bxl, bxr = mMetrics.bxr, by = mMetrics.by; // get horizontal extents and vertical position of the bar
float
dx = dox + bxl + (bxr - bxl) * ((mValue - mMinVal) / (mMaxVal - mMinVal)),
dy = by + doy;
return new Rect(Math.round(dx), Math.round(dy), Math.round(dx+dw), Math.round(dy+dh));
}
private Rect getBarBox()
{
// recalculate metrics, and then populate local copies
calcMetrics();
float dw = mMetrics.dw, dh = mMetrics.dh, dox = mMetrics.dox, doy = mMetrics.doy, // get size and origin of thumb drawable
bxl = mMetrics.bxl, bxr = mMetrics.bxr, by = mMetrics.by;
return new Rect(Math.round(bxl+dox), Math.round(by+doy), Math.round(bxr+dox+dw), Math.round(by+doy+dh));
}
private float getValueAtX(float x)
{
// recalculate metrics, and then populate local copies
calcMetrics();
float bxl = mMetrics.bxl, bxr = mMetrics.bxr;
if(x < bxl) x = bxl;
if(x > bxr) x = bxr;
return getMinVal()+((x - bxl)/(bxr-bxl))*(getMaxVal()-getMinVal());
}
private float getXAtValue(float v)
{
// recalculate metrics, and then populate local copies
calcMetrics();
float bxl = mMetrics.bxl, bxr = mMetrics.bxr;
float minv = getMinVal(), maxv = getMaxVal();
if(v < minv) v = minv;
if(v > maxv) v = maxv;
return bxl + ((v - minv) / (maxv - minv)) * (bxr - bxl);
}
// ======================================
public void setValue(float mValue)
{
if(mValue < getMinVal()) mValue = getMinVal();
if(mValue > getMaxVal()) mValue = getMaxVal();
this.mValue = mValue;
invalidate();
}
public float getValue()
{
return mValue;
}
public void setMinVal(float mMinVal)
{
this.mMinVal = mMinVal;
invalidate();
}
public float getMinVal()
{
return mMinVal;
}
public void setMaxVal(float mMaxVal)
{
this.mMaxVal = mMaxVal;
invalidate();
}
public float getMaxVal()
{
return mMaxVal;
}
public void setDotColor(int color)
{
// TODO: Reach inside that StateListDrawable and fuck up some Drawable getPaint().setColor() methods
this.mDotColor = color;
//setDotDefaultDrawable();
if(mIsDefaultDotDrawable)
{
this.setDefaultDotDrawable();
invalidate();
}
}
public void setDotActiveColor(int color)
{
// TODO: Reach inside that StateListDrawable and fuck up some Drawable getPaint().setColor() methods
this.mDotActiveColor = color;
//setDotDefaultDrawable();
if(mIsDefaultDotDrawable)
{
this.setDefaultDotDrawable();
invalidate();
}
}
public void setDotDrawable(Drawable mDotDrawable)
{
if(mDotDrawable != null) {
mIsDefaultDotDrawable = false;
this.mDotDrawable = mDotDrawable;
}
else {
mIsDefaultDotDrawable = true;
this.setDefaultDotDrawable();
}
requestLayout();
invalidate();
}
public Drawable getDotDrawable()
{
return mDotDrawable;
}
public void setTickThickness(float mTickThickness)
{
this.mTickThickness = mTickThickness;
mTickPaint.setStrokeWidth(mTickThickness);
requestLayout();
invalidate();
}
public float getTickThickness()
{
return mTickThickness;
}
public void setTickPadding(float mTickPadding)
{
this.mTickPadding = mTickPadding;
requestLayout();
invalidate();
}
public float getTickPadding()
{
return mTickPadding;
}
public void setBarPadding(float mBarPadding)
{
this.mBarPadding = mBarPadding;
requestLayout();
invalidate();
}
public float getBarPadding()
{
return mBarPadding;
}
public void setTickHeight(float mTickHeight)
{
this.mTickHeight = mTickHeight;
requestLayout();
invalidate();
}
public float getTickHeight()
{
return mTickHeight;
}
public void setBarThickness(float mBarThickness)
{
this.mBarThickness = mBarThickness;
mBarPaint.setStrokeWidth(mBarThickness);
requestLayout();
invalidate();
}
public float getBarThickness()
{
return mBarThickness;
}
public void setTicks(ArraySet<Float> mTicks)
{
this.mTicks = mTicks;
requestLayout();
invalidate();
}
public ArraySet<Float> getTicks()
{
return mTicks;
}
/**
* Sets the text to display in this label
* @param text The text to display. This will be drawn as one line.
*/
public void setText(String text)
{
mText = text;
requestLayout();
invalidate();
}
/**
* Sets the text size for this label
* @param size Font size
*/
public void setTextSize(int size)
{
// This text size has been pre-scaled by the getDimensionPixelOffset method
mTextPaint.setTextSize(size);
requestLayout();
invalidate();
}
/**
* Sets the text color for this label.
* @param color ARGB value for the text
*/
public void setTextColor(int color)
{
mTextPaint.setColor(color);
invalidate();
}
public void setBarColor(int color)
{
mBarPaint.setColor(color);
invalidate();
}
public void setTickColor(int color)
{
mTickPaint.setColor(color);
invalidate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment