I read the sourec code RangeSeekBar.java in https://github.com/anothem/android-range-seek-bar/tree/master/rangeseekbar
Normally, in order to use string resource file, we should "import info.dao.myapp.R;"
But in the RangeSeekBar.java, I can't find any resource file import , but the class can use R.string.demo_min_label, why?
package org.florescu.android.rangeseekbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ImageView;
import org.florescu.android.util.BitmapUtil;
import org.florescu.android.util.PixelUtil;
import java.math.BigDecimal;
*/
public class RangeSeekBar<T extends Number> extends ImageView {
/**
* Default color of a {#link RangeSeekBar}, #FF33B5E5. This is also known as "Ice Cream Sandwich" blue.
*/
public static final int ACTIVE_COLOR = Color.argb(0xFF, 0x33, 0xB5, 0xE5);
/**
* An invalid pointer id.
*/
public static final int INVALID_POINTER_ID = 255;
// Localized constants from MotionEvent for compatibility
// with API < 8 "Froyo".
public static final int ACTION_POINTER_INDEX_MASK = 0x0000ff00, ACTION_POINTER_INDEX_SHIFT = 8;
public static final Integer DEFAULT_MINIMUM = 0;
public static final Integer DEFAULT_MAXIMUM = 100;
public static final int HEIGHT_IN_DP = 30;
public static final int TEXT_LATERAL_PADDING_IN_DP = 3;
private static final int INITIAL_PADDING_IN_DP = 8;
private static final int DEFAULT_TEXT_SIZE_IN_DP = 14;
private static final int DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP = 8;
private static final int DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP = 8;
private static final int LINE_HEIGHT_IN_DP = 1;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint shadowPaint = new Paint();
private Bitmap thumbImage;
private Bitmap thumbPressedImage;
private Bitmap thumbDisabledImage;
private float mThumbHalfWidth;
private float mThumbHalfHeight;
private float padding;
private T absoluteMinValue, absoluteMaxValue;
private NumberType numberType;
private double absoluteMinValuePrim, absoluteMaxValuePrim;
private double normalizedMinValue = 0d;
private double normalizedMaxValue = 1d;
private Thumb pressedThumb = null;
private boolean notifyWhileDragging = false;
private OnRangeSeekBarChangeListener<T> listener;
private float mDownMotionX;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaledTouchSlop;
private boolean mIsDragging;
private int mTextOffset;
private int mTextSize;
private int mDistanceToTop;
private RectF mRect;
private boolean mSingleThumb;
private boolean mAlwaysActive;
private boolean mShowLabels;
private boolean mShowTextAboveThumbs;
private float mInternalPad;
private int mActiveColor;
private int mDefaultColor;
private int mTextAboveThumbsColor;
private boolean mThumbShadow;
private int mThumbShadowXOffset;
private int mThumbShadowYOffset;
private int mThumbShadowBlur;
private Path mThumbShadowPath;
private Path mTranslatedThumbShadowPath = new Path();
private Matrix mThumbShadowMatrix = new Matrix();
private boolean mActivateOnDefaultValues;
public RangeSeekBar(Context context) {
super(context);
init(context, null);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RangeSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
#SuppressWarnings("unchecked")
private T extractNumericValueFromAttributes(TypedArray a, int attribute, int defaultValue) {
TypedValue tv = a.peekValue(attribute);
if (tv == null) {
return (T) Integer.valueOf(defaultValue);
}
int type = tv.type;
if (type == TypedValue.TYPE_FLOAT) {
return (T) Float.valueOf(a.getFloat(attribute, defaultValue));
} else {
return (T) Integer.valueOf(a.getInteger(attribute, defaultValue));
}
}
private void init(Context context, AttributeSet attrs) {
float barHeight;
int thumbNormal = R.drawable.seek_thumb_normal;
int thumbPressed = R.drawable.seek_thumb_pressed;
int thumbDisabled = R.drawable.seek_thumb_disabled;
int thumbShadowColor;
int defaultShadowColor = Color.argb(75, 0, 0, 0);
int defaultShadowYOffset = PixelUtil.dpToPx(context, 2);
int defaultShadowXOffset = PixelUtil.dpToPx(context, 0);
int defaultShadowBlur = PixelUtil.dpToPx(context, 2);
if (attrs == null) {
setRangeToDefaultValues();
mInternalPad = PixelUtil.dpToPx(context, INITIAL_PADDING_IN_DP);
barHeight = PixelUtil.dpToPx(context, LINE_HEIGHT_IN_DP);
mActiveColor = ACTIVE_COLOR;
mDefaultColor = Color.GRAY;
mAlwaysActive = false;
mShowTextAboveThumbs = true;
mTextAboveThumbsColor = Color.WHITE;
thumbShadowColor = defaultShadowColor;
mThumbShadowXOffset = defaultShadowXOffset;
mThumbShadowYOffset = defaultShadowYOffset;
mThumbShadowBlur = defaultShadowBlur;
mActivateOnDefaultValues = false;
} else {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar, 0, 0);
try {
setRangeValues(
extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMinValue, DEFAULT_MINIMUM),
extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMaxValue, DEFAULT_MAXIMUM)
);
mShowTextAboveThumbs = a.getBoolean(R.styleable.RangeSeekBar_valuesAboveThumbs, true);
mTextAboveThumbsColor = a.getColor(R.styleable.RangeSeekBar_textAboveThumbsColor, Color.WHITE);
mSingleThumb = a.getBoolean(R.styleable.RangeSeekBar_singleThumb, false);
mShowLabels = a.getBoolean(R.styleable.RangeSeekBar_showLabels, true);
mInternalPad = a.getDimensionPixelSize(R.styleable.RangeSeekBar_internalPadding, INITIAL_PADDING_IN_DP);
barHeight = a.getDimensionPixelSize(R.styleable.RangeSeekBar_barHeight, LINE_HEIGHT_IN_DP);
mActiveColor = a.getColor(R.styleable.RangeSeekBar_activeColor, ACTIVE_COLOR);
mDefaultColor = a.getColor(R.styleable.RangeSeekBar_defaultColor, Color.GRAY);
mAlwaysActive = a.getBoolean(R.styleable.RangeSeekBar_alwaysActive, false);
Drawable normalDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbNormal);
if (normalDrawable != null) {
thumbImage = BitmapUtil.drawableToBitmap(normalDrawable);
}
Drawable disabledDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbDisabled);
if (disabledDrawable != null) {
thumbDisabledImage = BitmapUtil.drawableToBitmap(disabledDrawable);
}
Drawable pressedDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbPressed);
if (pressedDrawable != null) {
thumbPressedImage = BitmapUtil.drawableToBitmap(pressedDrawable);
}
mThumbShadow = a.getBoolean(R.styleable.RangeSeekBar_thumbShadow, false);
thumbShadowColor = a.getColor(R.styleable.RangeSeekBar_thumbShadowColor, defaultShadowColor);
mThumbShadowXOffset = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowXOffset, defaultShadowXOffset);
mThumbShadowYOffset = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowYOffset, defaultShadowYOffset);
mThumbShadowBlur = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowBlur, defaultShadowBlur);
mActivateOnDefaultValues = a.getBoolean(R.styleable.RangeSeekBar_activateOnDefaultValues, false);
} finally {
a.recycle();
}
}
if (thumbImage == null) {
thumbImage = BitmapFactory.decodeResource(getResources(), thumbNormal);
}
if (thumbPressedImage == null) {
thumbPressedImage = BitmapFactory.decodeResource(getResources(), thumbPressed);
}
if (thumbDisabledImage == null) {
thumbDisabledImage = BitmapFactory.decodeResource(getResources(), thumbDisabled);
}
mThumbHalfWidth = 0.5f * thumbImage.getWidth();
mThumbHalfHeight = 0.5f * thumbImage.getHeight();
setValuePrimAndNumberType();
mTextSize = PixelUtil.dpToPx(context, DEFAULT_TEXT_SIZE_IN_DP);
mDistanceToTop = PixelUtil.dpToPx(context, DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP);
mTextOffset = !mShowTextAboveThumbs ? 0 : this.mTextSize + PixelUtil.dpToPx(context,
DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP) + this.mDistanceToTop;
mRect = new RectF(padding,
mTextOffset + mThumbHalfHeight - barHeight / 2,
getWidth() - padding,
mTextOffset + mThumbHalfHeight + barHeight / 2);
// make RangeSeekBar focusable. This solves focus handling issues in case EditText widgets are being used along with the RangeSeekBar within ScrollViews.
setFocusable(true);
setFocusableInTouchMode(true);
mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
if (mThumbShadow) {
// We need to remove hardware acceleration in order to blur the shadow
setLayerType(LAYER_TYPE_SOFTWARE, null);
shadowPaint.setColor(thumbShadowColor);
shadowPaint.setMaskFilter(new BlurMaskFilter(mThumbShadowBlur, BlurMaskFilter.Blur.NORMAL));
mThumbShadowPath = new Path();
mThumbShadowPath.addCircle(0,
0,
mThumbHalfHeight,
Path.Direction.CW);
}
}
#SuppressWarnings("unchecked")
// only used to set default values when initialised from XML without any values specified
private void setRangeToDefaultValues() {
this.absoluteMinValue = (T) DEFAULT_MINIMUM;
this.absoluteMaxValue = (T) DEFAULT_MAXIMUM;
setValuePrimAndNumberType();
}
private void setValuePrimAndNumberType() {
absoluteMinValuePrim = absoluteMinValue.doubleValue();
absoluteMaxValuePrim = absoluteMaxValue.doubleValue();
numberType = NumberType.fromNumber(absoluteMinValue);
}
/**
* Should the widget notify the listener callback while the user is still dragging a thumb? Default is false.
*/
#SuppressWarnings("unused")
public void setNotifyWhileDragging(boolean flag) {
this.notifyWhileDragging = flag;
}
/**
* Returns the currently selected min value.
*
* #return The currently selected min value.
*/
public T getSelectedMinValue() {
return normalizedToValue(normalizedMinValue);
}
/**
* Sets the currently selected minimum value. The widget will be invalidated and redrawn.
*
* #param value The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range.
*/
public void setSelectedMinValue(T value) {
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
setNormalizedMinValue(0d);
} else {
setNormalizedMinValue(valueToNormalized(value));
}
}
/**
* Returns the currently selected max value.
*
* #return The currently selected max value.
*/
public T getSelectedMaxValue() {
return normalizedToValue(normalizedMaxValue);
}
/**
* Sets the currently selected maximum value. The widget will be invalidated and redrawn.
*
* #param value The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range.
*/
public void setSelectedMaxValue(T value) {
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
setNormalizedMaxValue(1d);
} else {
setNormalizedMaxValue(valueToNormalized(value));
}
}
#SuppressWarnings("unused")
public void setOnRangeSeekBarChangeListener(OnRangeSeekBarChangeListener<T> listener) {
this.listener = listener;
}
#SuppressWarnings("unused")
public void setThumbShadowPath(Path thumbShadowPath) {
this.mThumbShadowPath = thumbShadowPath;
}
/**
* Draws the widget on the given canvas.
*/
#Override
protected synchronized void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
paint.setTextSize(mTextSize);
paint.setStyle(Style.FILL);
paint.setColor(mDefaultColor);
paint.setAntiAlias(true);
float minMaxLabelSize = 0;
if (mShowLabels) {
// draw min and max labels
String minLabel = getContext().getString(R.string.demo_min_label);
String maxLabel = getContext().getString(R.string.demo_max_label);
minMaxLabelSize = Math.max(paint.measureText(minLabel), paint.measureText(maxLabel));
float minMaxHeight = mTextOffset + mThumbHalfHeight + mTextSize / 3;
canvas.drawText(minLabel, 0, minMaxHeight, paint);
canvas.drawText(maxLabel, getWidth() - minMaxLabelSize, minMaxHeight, paint);
}
padding = mInternalPad + minMaxLabelSize + mThumbHalfWidth;
// draw seek bar background line
mRect.left = padding;
mRect.right = getWidth() - padding;
canvas.drawRect(mRect, paint);
boolean selectedValuesAreDefault = (getSelectedMinValue().equals(getAbsoluteMinValue()) &&
getSelectedMaxValue().equals(getAbsoluteMaxValue()));
int colorToUseForButtonsAndHighlightedLine = !mAlwaysActive && !mActivateOnDefaultValues && selectedValuesAreDefault ?
mDefaultColor : // default values
mActiveColor; // non default, filter is active
// draw seek bar active range line
mRect.left = normalizedToScreen(normalizedMinValue);
mRect.right = normalizedToScreen(normalizedMaxValue);
paint.setColor(colorToUseForButtonsAndHighlightedLine);
canvas.drawRect(mRect, paint);
// draw minimum thumb (& shadow if requested) if not a single thumb control
if (!mSingleThumb) {
if (mThumbShadow) {
drawThumbShadow(normalizedToScreen(normalizedMinValue), canvas);
}
drawThumb(normalizedToScreen(normalizedMinValue), Thumb.MIN.equals(pressedThumb), canvas,
selectedValuesAreDefault);
}
// draw maximum thumb & shadow (if necessary)
if (mThumbShadow) {
drawThumbShadow(normalizedToScreen(normalizedMaxValue), canvas);
}
drawThumb(normalizedToScreen(normalizedMaxValue), Thumb.MAX.equals(pressedThumb), canvas,
selectedValuesAreDefault);
// draw the text if sliders have moved from default edges
if (mShowTextAboveThumbs && (mActivateOnDefaultValues || !selectedValuesAreDefault)) {
paint.setTextSize(mTextSize);
paint.setColor(mTextAboveThumbsColor);
// give text a bit more space here so it doesn't get cut off
int offset = PixelUtil.dpToPx(getContext(), TEXT_LATERAL_PADDING_IN_DP);
String minText = String.valueOf(getSelectedMinValue());
String maxText = String.valueOf(getSelectedMaxValue());
float minTextWidth = paint.measureText(minText) + offset;
float maxTextWidth = paint.measureText(maxText) + offset;
if (!mSingleThumb) {
canvas.drawText(minText,
normalizedToScreen(normalizedMinValue) - minTextWidth * 0.5f,
mDistanceToTop + mTextSize,
paint);
}
canvas.drawText(maxText,
normalizedToScreen(normalizedMaxValue) - maxTextWidth * 0.5f,
mDistanceToTop + mTextSize,
paint);
}
}
}
But have you tried the git the project to your workspace and build it locally successful?
Related
I'm trying to make small App. This App have Activity, Custom View Class, and service.
1) Activity ask service for new Data and redraw Custom view
2) Service is listning to Bluetooth device and parse data.
Everything was fine, but I noticed that App is slowing down after 40 mins working.
I made another project remove service and find that it slowing too! So problem is my Customview class, maybe i have memory leaks in service to... but i have problem with drawings 100%.
I found that i have some objects that i'm creating on onDraw() method.. i try to move all thise staff to onSizeChanged() - but get more lags.
And now i need help. I need some example with simple drawings that depends on device width and height (I think my method is wrong - i use proportions of my 'Design' to calculate demetions in px)
By the way i'm using animator which make animations more smooth))
public class Dynamics {
/**
* Used to compare floats, if the difference is smaller than this, they are
* considered equal
*/
private static final float TOLERANCE = 0.01f;
/** The position the dynamics should to be at */
private float targetPosition;
/** The current position of the dynamics */
private float position;
/** The current velocity of the dynamics */
private float velocity;
/** The time the last update happened */
private long lastTime;
/** The amount of springiness that the dynamics has */
private float springiness;
/** The damping that the dynamics has */
private double damping;
public Dynamics(float springiness, float dampingRatio) {
this.springiness = springiness;
this.damping = dampingRatio * 2 * Math.sqrt(springiness);
}
public void setPosition(float position, long now) {
this.position = position;
lastTime = now;
}
public void setVelocity(float velocity, long now) {
this.velocity = velocity;
lastTime = now;
}
public void setTargetPosition(float targetPosition, long now) {
this.targetPosition = targetPosition;
lastTime = now;
}
public void update(long now) {
float dt = Math.min(now - lastTime, 50) / 1000f;
float x = position - targetPosition;
double acceleration = -springiness * x - damping * velocity;
velocity += acceleration * dt;
position += velocity * dt;
lastTime = now;
}
public boolean isAtRest() {
final boolean standingStill = Math.abs(velocity) < TOLERANCE;
final boolean isAtTarget = (targetPosition - position) < TOLERANCE;
return standingStill && isAtTarget;
}
public float getPosition() {
return position;
}
public float getTargetPos() {
return targetPosition;
}
public float getVelocity() {
return velocity;
}
}
In my Custom view i have this to set new data:
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
LastData=NewData;
//redraw();
}
Thise is "code" of my custom view, after all changes it's look terible, so i cut 90% of it. And i make some test code insted:
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AnimationUtils;
import java.io.IOException;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Random;
public class CustomDisplayView extends View {
//paint for drawing custom view
private Paint RectPaint = new Paint();
//Динамические данные float
private Dynamics[] datapoints;
//Динамические статические Int
private int[] NewData = new int[500];
//созадем новый объект квадрат
private RectF rectf= new RectF();
//Задаем массив динамических цветов
int[] CurColors= new int[100];
int[] TargetColors= new int[100];
public CustomDisplayView(Context context, AttributeSet attrs){
super(context, attrs);
//Установка парметров красок
RectPaint.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != 0 && h != 0) {
//create Bitmap here
}
}
/**
* Override the onDraw method to specify custom view appearance using canvas
*/
#Override
protected void onDraw(Canvas canvas) {
//Get Screen size
//int viewWidth=this.getMeasuredWidth();
// int viewHeight = this.getMeasuredHeight();
//Выводим код цвета
RectPaint.setColor(0xff000000);
RectPaint.setTextSize(40);
canvas.restore();
canvas.drawText("V: " + datapoints[1].getPosition(), 20, 60, RectPaint);
//int saveCount = canvas.save();
for(int a=0;a<1000;a++)
{
rectf.set(datapoints[a].getPosition(), datapoints[a + 1].getPosition(), datapoints[a].getPosition() + datapoints[a + 1].getPosition() / 10, datapoints[a + 1].getPosition() + datapoints[a + 1].getPosition() / 10);
RectPaint.setColor(0x88005020);
//RectPaint.setColor(CurColor[a]);
//canvas.rotate(datapoints[1].getPosition(), viewWidth/2, viewHeight/2);
canvas.drawRoundRect(rectf, 0, 0, RectPaint);
//canvas.restore();
}
//canvas.restoreToCount(saveCount);
/*
for(int a=0;a<999;a++)
{
CurColors[a]=progressiveColor(CurColors[a], TargetColors[a], 2);
if(CurColors[a]==TargetColors[a])
{
TargetColors[a]=randomColor();
}
}
*/
canvas.restore();
}
//Рандом колор
public static int randomColor(){
Random random = new Random();
int[] ColorParams= new int[4];
ColorParams[0]=random.nextInt(235)+20;
ColorParams[1]=random.nextInt(255);
ColorParams[2]=random.nextInt(255);
ColorParams[3]=random.nextInt(255);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
}
//Интерполяция цвета
public static int progressiveColor(int CurColor,int TargetColor,int Step){
//Current color
int[] ColorParams= new int[4];
ColorParams[0]=(CurColor >> 24) & 0xFF;
ColorParams[1]=(CurColor >> 16) & 0xFF;
ColorParams[2]=(CurColor >> 8) & 0xFF;
ColorParams[3]=CurColor & 0xFF;
//TargetColor
int[] TargetColorParams= new int[4];
TargetColorParams[0]=(TargetColor >> 24) & 0xFF;
TargetColorParams[1]=(TargetColor >> 16) & 0xFF;
TargetColorParams[2]=(TargetColor >> 8) & 0xFF;
TargetColorParams[3]=TargetColor & 0xFF;
for(int i=0;i<4;i++)
{
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]+=Step;
if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
else if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]-=Step;
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
}
//int red = r - (int)((float)(r*255)/(float)all);
//int green = (int)((float)(g*255)/(float)all);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
//return String.format("#%06X", (0xFFFFFF & Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3])));
//return " "+opacity+" "+red+" "+green+" "+blue;
}
//each custom attribute should have a get and set method
//this allows updating these properties in Java
//we call these in the main Activity class
/**
* Get the current text label color
* #return color as an int
*/
public int getLabelColor(){
return 1;
}
/**
* Set the label color
* #param newColor new color as an int
*/
public void setLabelColor(int newColor){
//update the instance variable
//labelCol=newColor;
//redraw the view
invalidate();
requestLayout();
}
public void redraw(){
//redraw the view
invalidate();
requestLayout();
}
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
//redraw();
}
public int GetAction(float x,float y)
{
/*
if(x>(DicsCenterX-LineHalfSpeedZone) && x<(DicsCenterX+LineHalfSpeedZone) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
// private int SpeedZoneRadius2=0;
// private int PowerOutRadius=0;
//Смена режима
//начинаем смену размеру index / ms
ChangeVal(0,700);
return 1;
}
else if(x>(CofCantBGDrop*2) && x<(CofCantBGDrop*4) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
return 2;
}
else
{
return 0;
}
//return 0;
*/
return 1;
}
public static String fmt(double d)
{
double val = d/100;
String result;
if(val == (long) val)
result= String.format("%d",(long)d);
else
result= String.format("%s",d);
if(result.length()<2)
{
String result2=result;
result="0"+result2;
}
return result;
}
private Runnable animator = new Runnable() {
#Override
public void run() {
boolean needNewFrame = false;
long now = AnimationUtils.currentAnimationTimeMillis();
for (Dynamics dynamics : datapoints) {
dynamics.update(now);
if (!dynamics.isAtRest()) {
needNewFrame = true;
}
}
if (needNewFrame) {
postDelayed(this, 15);
}
invalidate();
}
};
}
I just want to understand where i need to declare scale values, where i need to calc real dimensions in px.. and et.c. to have no memory leaks..
If i remove color change and incrice number of Rects up to 1000 - i get lags.
All methods o any information how to debug memory leaks - you are wellcome!
You have to remove runnable for animation when view is detached.
if (needNewFrame) {
postDelayed(this, 15); <--- memory leak
}
Try like this.
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallback(your runnable);
}
Also refreshing every 15 milliseconds is very heavy.
I have TextView:
text.setTypeface(font);
text.setWidth((int)width);
text.setGravity(Gravity.CENTER);
text.setHeight((int)height);
text.setIncludeFontPadding(false);
text.setPadding(0,0,0,0);
However even with the padding set to 0, and setIncludeFontPadding to false and I set the font size to the height of the TextView I still get this:
If I set the padding to have negative values like -30, It fixes it:
text.setPadding(0,-30,0,-30);
My question is why do I have to do this? Where is this phantom padding coming from? And where am I finding this arbitrary (-30 in this specific case) value I need to set it to, so that the text fills the height?
Update
Trying #Mike M. 's solution I got these results. When it was a positive number, it was a smaller size than when it was a negative one. Both of them still had padding:
Update 2 Here the custom class in full:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.widget.TextView;
/**
* Special textview which gracefully handles resizing.
*/
public class iTextView extends TextView
{
// Set true to remove phantom padding
public boolean trimPadding = false;
//region Interfaces
private interface SizeTester
{
/**
* Interface for scaling text to fit.
* #param suggestedSize Size of text to be tested.
* #param availableSpace Available space in which text must fit.
* #return An integer < 0 if after applying {#code suggestedSize} to
* text, it takes less space than {#code availableSpace}, > 0
* otherwise.
*/
int onTestSize(int suggestedSize, RectF availableSpace);
}
//endregion
//region Variables
private static final int NO_LINE_LIMIT = -1;
private RectF _textRect = new RectF();
private RectF _availableSpaceRect;
private SparseIntArray _textCachedSizes;
private TextPaint _paint;
private float _maxTextSize;
private float _spacingMult;
private float _spacingAdd;
private float _minTextSize;
private int _widthLimit;
private int _maxLines;
private boolean _enableSizeCache;
private boolean _initialized;
//endregion
//region Constructors
public iTextView(Context context)
{
super(context);
initialize();
}
public iTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public iTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initialize();
}
//endregion
//region Initialization
private void initialize()
{
_spacingMult = 1.0f;
_spacingAdd = 0.0f;
_minTextSize = 20;
_enableSizeCache = true;
_paint = new TextPaint(getPaint());
_maxTextSize = getTextSize();
_availableSpaceRect = new RectF();
_textCachedSizes = new SparseIntArray();
if (_maxLines == 0)
{
// No value was assigned during construction
_maxLines = NO_LINE_LIMIT;
}
_initialized = true;
}
//endregion
//region Text Value
#Override
public void setText(final CharSequence text, BufferType type)
{
super.setText(text, type);
adjustTextSize(text.toString());
}
#Override
protected void onTextChanged(final CharSequence text, final int start, final int before,
final int after)
{
super.onTextChanged(text, start, before, after);
reAdjust();
}
//endregion
//region Text Sizing
#Override
public void setTextSize(float size)
{
_maxTextSize = size;
_textCachedSizes.clear();
adjustTextSize(getText().toString());
}
/**
* Ensures the text is as big as possible for the text area.
*/
public void setTextSizeToMaxFit()
{
_maxTextSize = 999;
_textCachedSizes.clear();
adjustTextSize(getText().toString());
}
#Override
public void setTextSize(int unit, float size)
{
Context context = getContext();
Resources resources;
if (context == null)
{
resources = Resources.getSystem();
} else
{
resources = context.getResources();
}
_maxTextSize = TypedValue.applyDimension(unit, size, resources.getDisplayMetrics());
_textCachedSizes.clear();
adjustTextSize(getText().toString());
}
/**
* Set the lower text size limit and invalidate the view
*
* #param minTextSize
*/
public void setMinTextSize(float minTextSize)
{
_minTextSize = minTextSize;
reAdjust();
}
private void reAdjust() {
adjustTextSize(getText().toString());
}
private void adjustTextSize(String string)
{
if (!_initialized)
{
return;
}
int startSize = (int) _minTextSize;
int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() - getCompoundPaddingTop();
_widthLimit = getMeasuredWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
_availableSpaceRect.right = _widthLimit;
_availableSpaceRect.bottom = heightLimit;
super.setTextSize
(
TypedValue.COMPLEX_UNIT_PX,
efficientTextSizeSearch(startSize, (int)_maxTextSize, mSizeTester, _availableSpaceRect)
);
}
private final SizeTester mSizeTester = new SizeTester()
{
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public int onTestSize(int suggestedSize, RectF availableSPace)
{
_paint.setTextSize(suggestedSize);
String text = getText().toString();
boolean singleLine = getMaxLines() == 1;
if (singleLine)
{
_textRect.bottom = _paint.getFontSpacing();
_textRect.right = _paint.measureText(text);
} else
{
StaticLayout layout = new StaticLayout
(
text,
_paint,
_widthLimit,
Alignment.ALIGN_NORMAL,
_spacingMult,
_spacingAdd,
true
);
// Return early if no more lines
if (getMaxLines() != NO_LINE_LIMIT && layout.getLineCount() > getMaxLines())
{
return 1;
}
_textRect.bottom = layout.getHeight();
int maxWidth = -1;
for (int i = 0; i < layout.getLineCount(); i++)
{
if (maxWidth < layout.getLineWidth(i))
{
maxWidth = (int)layout.getLineWidth(i);
}
}
_textRect.right = maxWidth;
}
_textRect.offsetTo(0, 0);
if (availableSPace.contains(_textRect))
{
// May be too small, Will find the best match later
return -1;
} else
{
// Too big
return 1;
}
}
};
/**
* Enables or disables size caching, enabling it will improve performance
* where its animating a value inside TextView. This stores the font
* size against getText().length() Enabling it as 0
* takes more space than 1 on some fonts and so on.
* #param enable Enable font size caching
*/
public void enableSizeCache(boolean enable)
{
_enableSizeCache = enable;
_textCachedSizes.clear();
adjustTextSize(getText().toString());
}
private int efficientTextSizeSearch(int start, int end, SizeTester sizeTester, RectF availableSpace)
{
if (!_enableSizeCache)
{
return binarySearch(start, end, sizeTester, availableSpace);
}
String text = getText().toString();
int key = text == null ? 0 : text.length();
int size = _textCachedSizes.get(key);
if (size != 0)
{
return size;
}
size = binarySearch(start, end, sizeTester, availableSpace);
_textCachedSizes.put(key, size);
return size;
}
#Override
protected void onSizeChanged(int width, int height, int oldwidth,int oldheight)
{
_textCachedSizes.clear();
super.onSizeChanged(width, height, oldwidth, oldheight);
if (width != oldwidth || height != oldheight)
{
reAdjust();
}
}
private static int binarySearch(int start, int end, SizeTester sizeTester,RectF availableSpace)
{
int lastBest = start;
int low = start;
int high = end - 1;
int mid = 0;
while (low <= high)
{
mid = (low + high) >>> 1;
int midValCmp = sizeTester.onTestSize(mid, availableSpace);
if (midValCmp < 0)
{
lastBest = low;
low = mid + 1;
} else if (midValCmp > 0)
{
high = mid - 1;
lastBest = high;
} else
{
return mid;
}
}
// Make sure to return last best
// This is what should always be returned
return lastBest;
}
//endregion
//region Text Lines
#Override
public void setMaxLines(int maxlines)
{
super.setMaxLines(maxlines);
_maxLines = maxlines;
reAdjust();
}
public int getMaxLines()
{
return _maxLines;
}
#Override
public void setSingleLine()
{
super.setSingleLine();
_maxLines = 1;
reAdjust();
}
#Override
public void setSingleLine(boolean singleLine)
{
super.setSingleLine(singleLine);
if (singleLine)
{
_maxLines = 1;
} else
{
_maxLines = NO_LINE_LIMIT;
}
reAdjust();
}
#Override
public void setLines(int lines)
{
super.setLines(lines);
_maxLines = lines;
reAdjust();
}
#Override
public void setLineSpacing(float add, float mult)
{
super.setLineSpacing(add, mult);
_spacingMult = mult;
_spacingAdd = add;
}
//endregion
//region Padding Fix
#Override
protected void onDraw(Canvas canvas)
{
if (trimPadding)
{
trimVertical();
}
super.onDraw(canvas);
}
private void trimVertical()
{
final Layout layout = getLayout();
final Rect textBounds = new Rect();
if (layout == null)
{
Log.d("Layout is null","" + layout);
return;
}
int baseline = layout.getLineBaseline(0);
getTextBounds(0, textBounds);
final int pTop = baseline + textBounds.top;
final int lastLine = getLineCount() - 1;
baseline = layout.getLineBaseline(lastLine);
getTextBounds(lastLine, textBounds);
final int pBottom = layout.getHeight() - baseline - textBounds.bottom + 1;
setPadding(getPaddingLeft(), -pTop, getPaddingRight(), -pBottom);
}
private void getTextBounds(int line, Rect bounds)
{
final String s = getText().toString();
final int start = getLayout().getLineStart(line);
final int end = getLayout().getLineEnd(line);
getPaint().getTextBounds(s, start, end, bounds);
}
//endregion
}
I have created a class to auto resize TextView here is the code:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.RectF;
import android.os.Build;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.widget.TextView;
public class AutoResizeTextView extends TextView {
private interface SizeTester {
/**
*
* #param suggestedSize
* Size of text to be tested
* #param availableSpace
* available space in which text must fit
* #return an integer < 0 if after applying {#code suggestedSize} to
* text, it takes less space than {#code availableSpace}, > 0
* otherwise
*/
public int onTestSize(int suggestedSize, RectF availableSpace);
}
private RectF mTextRect = new RectF();
private RectF mAvailableSpaceRect;
private SparseIntArray mTextCachedSizes;
private TextPaint mPaint;
private float mMaxTextSize;
private float mSpacingMult = 1.0f;
private float mSpacingAdd = 0.0f;
private float mMinTextSize = 5;
private int mWidthLimit;
private static final int NO_LINE_LIMIT = -1;
private int mMaxLines;
private boolean mEnableSizeCache = true;
private boolean mInitiallized;
public AutoResizeTextView(Context context) {
super(context);
initialize();
}
public AutoResizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
private void initialize() {
mPaint = new TextPaint(getPaint());
mMaxTextSize = getTextSize();
mAvailableSpaceRect = new RectF();
mTextCachedSizes = new SparseIntArray();
if (mMaxLines == 0) {
// no value was assigned during construction
mMaxLines = NO_LINE_LIMIT;
}
mInitiallized = true;
}
#Override
public void setText(final CharSequence text, BufferType type) {
super.setText(text, type);
adjustTextSize(text.toString());
}
#Override
public void setTextSize(float size) {
mMaxTextSize = size;
mTextCachedSizes.clear();
adjustTextSize(getText().toString());
}
#Override
public void setMaxLines(int maxlines) {
super.setMaxLines(maxlines);
mMaxLines = maxlines;
reAdjust();
}
public int getMaxLines() {
return mMaxLines;
}
#Override
public void setSingleLine() {
super.setSingleLine();
mMaxLines = 1;
reAdjust();
}
#Override
public void setSingleLine(boolean singleLine) {
super.setSingleLine(singleLine);
if (singleLine) {
mMaxLines = 1;
} else {
mMaxLines = NO_LINE_LIMIT;
}
reAdjust();
}
#Override
public void setLines(int lines) {
super.setLines(lines);
mMaxLines = lines;
reAdjust();
}
#Override
public void setTextSize(int unit, float size) {
Context c = getContext();
Resources r;
if (c == null)
r = Resources.getSystem();
else
r = c.getResources();
mMaxTextSize = TypedValue.applyDimension(unit, size,
r.getDisplayMetrics());
mTextCachedSizes.clear();
adjustTextSize(getText().toString());
}
#Override
public void setLineSpacing(float add, float mult) {
super.setLineSpacing(add, mult);
mSpacingMult = mult;
mSpacingAdd = add;
}
/**
* Set the lower text size limit and invalidate the view
*
* #param minTextSize
*/
public void setMinTextSize(float minTextSize) {
mMinTextSize = minTextSize;
reAdjust();
}
private void reAdjust() {
adjustTextSize(getText().toString());
}
private void adjustTextSize(String string) {
if (!mInitiallized) {
return;
}
int startSize = (int) mMinTextSize;
int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom()
- getCompoundPaddingTop();
mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft()
- getCompoundPaddingRight();
mAvailableSpaceRect.right = mWidthLimit;
mAvailableSpaceRect.bottom = heightLimit;
super.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
efficientTextSizeSearch(startSize, (int) mMaxTextSize,
mSizeTester, mAvailableSpaceRect));
}
private final SizeTester mSizeTester = new SizeTester() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public int onTestSize(int suggestedSize, RectF availableSPace) {
mPaint.setTextSize(suggestedSize);
String text = getText().toString();
boolean singleline = getMaxLines() == 1;
if (singleline) {
mTextRect.bottom = mPaint.getFontSpacing();
mTextRect.right = mPaint.measureText(text);
} else {
StaticLayout layout = new StaticLayout(text, mPaint,
mWidthLimit, Alignment.ALIGN_NORMAL, mSpacingMult,
mSpacingAdd, true);
// return early if we have more lines
if (getMaxLines() != NO_LINE_LIMIT
&& layout.getLineCount() > getMaxLines()) {
return 1;
}
mTextRect.bottom = layout.getHeight();
int maxWidth = -1;
for (int i = 0; i < layout.getLineCount(); i++) {
if (maxWidth < layout.getLineWidth(i)) {
maxWidth = (int) layout.getLineWidth(i);
}
}
mTextRect.right = maxWidth;
}
mTextRect.offsetTo(0, 0);
if (availableSPace.contains(mTextRect)) {
// may be too small, don't worry we will find the best match
return -1;
} else {
// too big
return 1;
}
}
};
/**
* Enables or disables size caching, enabling it will improve performance
* where you are animating a value inside TextView. This stores the font
* size against getText().length() Be careful though while enabling it as 0
* takes more space than 1 on some fonts and so on.
*
* #param enable
* enable font size caching
*/
public void enableSizeCache(boolean enable) {
mEnableSizeCache = enable;
mTextCachedSizes.clear();
adjustTextSize(getText().toString());
}
private int efficientTextSizeSearch(int start, int end,
SizeTester sizeTester, RectF availableSpace) {
if (!mEnableSizeCache) {
return binarySearch(start, end, sizeTester, availableSpace);
}
String text = getText().toString();
int key = text == null ? 0 : text.length();
int size = mTextCachedSizes.get(key);
if (size != 0) {
return size;
}
size = binarySearch(start, end, sizeTester, availableSpace);
mTextCachedSizes.put(key, size);
return size;
}
private static int binarySearch(int start, int end, SizeTester sizeTester,
RectF availableSpace) {
int lastBest = start;
int lo = start;
int hi = end - 1;
int mid = 0;
while (lo <= hi) {
mid = (lo + hi) >>> 1;
int midValCmp = sizeTester.onTestSize(mid, availableSpace);
if (midValCmp < 0) {
lastBest = lo;
lo = mid + 1;
} else if (midValCmp > 0) {
hi = mid - 1;
lastBest = hi;
} else {
return mid;
}
}
// make sure to return last best
// this is what should always be returned
return lastBest;
}
#Override
protected void onTextChanged(final CharSequence text, final int start,
final int before, final int after) {
super.onTextChanged(text, start, before, after);
reAdjust();
}
#Override
protected void onSizeChanged(int width, int height, int oldwidth,
int oldheight) {
mTextCachedSizes.clear();
super.onSizeChanged(width, height, oldwidth, oldheight);
if (width != oldwidth || height != oldheight) {
reAdjust();
}
}
}
As you can see in this class I have set the minimum text size to 5. The resizing works perfectly when I type in the text in my xml file. However when I try to change the text during the activity after grabbing the text from a network connection, I change the text in my onPostExecute() method, however when the text loads on screen it appears really small (i'm assuming it is appearing as the minimum size 5 text I set in the class). I don't understand why it is not getting resized bigger since it fits. In my xml file I set the textSize to 12 (which means 12 would be the max size). I have even tried changing the text size manually in the activity but this does not work either, the text still displays as size 5. Here is my code:
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ConfirmBookBuy extends Activity
{
Globals g;
LinearLayout mainLinearLayout;
ProgressBar loadingWheel;
TextView titleInfo;
TextView authorInfo;
TextView editionInfo;
TextView publisherInfo;
TextView datePublishedInfo;
TextView bindingInfo;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.buy_confirm_book_layout);
g = Globals.getInstance();
mainLinearLayout = (LinearLayout)findViewById(R.id.mainLinearLayout);
loadingWheel = (ProgressBar)findViewById(R.id.loadingWheel);
titleInfo = (TextView)findViewById(R.id.titleInfo);
authorInfo = (TextView)findViewById(R.id.authorInfo);
editionInfo = (TextView)findViewById(R.id.editionInfo);
publisherInfo = (TextView)findViewById(R.id.publisherInfo);
datePublishedInfo = (TextView)findViewById(R.id.datePublishedInfo);
bindingInfo = (TextView)findViewById(R.id.bindingInfo);
new ConfirmIsbn().execute();
}
public class ConfirmIsbn extends AsyncTask<String, Void, Void>
{
#Override
protected Void doInBackground(String... params) {
// grabbing the text from internet, this works, I have tested to see that it is actually grabbing the text
return null;
}
#Override
protected void onPostExecute(Void aVoid)
{
super.onPostExecute(aVoid);
titleInfo.setText(g.getBuyingTitle());
authorInfo.setText(g.getBuyingAuthor());
editionInfo.setText(g.getBuyingEdition());
publisherInfo.setText(g.getBuyingPublisher());
datePublishedInfo.setText(g.getBuyingDatePublished());
bindingInfo.setText(g.getBuyingBinding());
titleInfo.setTextSize(12);
authorInfo.setTextSize(12);
editionInfo.setTextSize(12);
publisherInfo.setTextSize(12);
datePublishedInfo.setTextSize(12);
bindingInfo.setTextSize(12);
}
}
}
I just want my text view to auto resize to the biggest text size that will fit (max of 12). I don't get why when I set the text in xml the resizing works perfectly, however when I try to set it during the running of activity it will always just display the minimum text of size 5... even if I try to manually set the text in code too.
I have used this tutorial https://code.google.com/p/range-seek-bar/#Example_usage_as_Integer_range?.
Encountered runtime error of my activity stopped. Would like to seek help from you. I attempted to correct the following compile errors as listed below.
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, context);
Context cannot be resolved to a variable
I tried adding changing context to this.
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
TAG cannot be resolved to a variable.
I tried adding "protected static final String TAG = null;" to main activity.
ViewGroup layout = (ViewGroup) findViewById(<your-layout-id>)
Does the layout id refer to my main_activity.xml in my layout?
Really grateful for your feedback.
MainActivity.Java
package com.example.rangeseekbargooglecode;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.ViewGroup;
import com.example.rangeseekbargooglecode.RangeSeekBar.OnRangeSeekBarChangeListener;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String TAG = null;
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
}
});
// add RangeSeekBar to pre-defined layout
ViewGroup layout = (ViewGroup) findViewById(R.layout.activity_main);
layout.addView(seekBar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="109dp" />
</RelativeLayout>
Edited Code to allow TextView to display range.
public class MainActivity extends Activity {
private TextView textview;
protected static final String TAG = "com.example.gto_doubleseekbar";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.textView1);
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
String powerranger = "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue;
Log.i(TAG, powerranger);
textview.setText(powerranger);
}
});
// add RangeSeekBar to pre-defined layout
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
}
RangeSeekBar seekBar = new RangeSeekBar(20, 75, context); 1. Context cannot be resolved to a variable
this must work:
RangeSeekBar seekBar = new RangeSeekBar(20, 75, this);
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue); 2. TAG cannot be resolved to a variable. I tried adding "protected static final String TAG = null;" to main activity.
Don't set it to null. Usually you use the app or component name, e.g.
protected static final String TAG = "MyApp";
ViewGroup layout = (ViewGroup) findViewById() 3. Does the layout id refer to my main_activity.xml in my layout?
Use this:
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService (Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
Try to implement custom RangeSeekBar.
xml file:
<com.doondoz.utility.common_function.RangeSeekBar
android:id="#+id/seekBarPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:left_index="0"
android:layout_weight="0.90" />
java file:
RangeSeekBar.java
public class RangeSeekBar extends View {
private static final int DEFAULT_HEIGHT = 70;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_TICK_COUNT = 100;
private Thumb leftThumb, rightThumb;
private Thumb pressedThumb = null;
private SeekBar seekBar;
private Paint thumbPaint;
private OnRangeSeekBarChangerListener mListener;
private int mTickCount;
private int mLeftIndex = 0;
private int mRightIndex;
private int mThumbColor;
private int mThumbNormalRadius;
private int mThumbPressedRadius;
public RangeSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RangeSeekBar(Context context) {
super(context);
}
#SuppressWarnings("deprecation")
private void init(Context context, AttributeSet attrs) {
Resources resources = getResources();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RangeSeekBar);
try {
mTickCount = typedArray.getInteger(R.styleable.RangeSeekBar_tick_count, DEFAULT_TICK_COUNT);
mRightIndex = mTickCount - 1;
mThumbColor = typedArray.getColor(R.styleable.RangeSeekBar_thumb_color, getResources().getColor(R.color.thumb_default));
mThumbNormalRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_normal_radius, 12);
mThumbPressedRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_pressed_radius, 16);
mLeftIndex = typedArray.getInteger(R.styleable.RangeSeekBar_left_index, 0);
mRightIndex = typedArray.getInteger(R.styleable.RangeSeekBar_right_index, mRightIndex);
if (mLeftIndex < 0)
throw new IllegalArgumentException("Left index must be >= 0");
if (mRightIndex > mTickCount)
throw new IllegalArgumentException("Right index must be <= tick count");
} finally {
typedArray.recycle();
}
setUp();
}
private void setUp() {
thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thumbPaint.setStyle(Paint.Style.FILL);
thumbPaint.setColor(mThumbColor);
leftThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
rightThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
seekBar = new SeekBar(0, 0, 0, Color.BLACK, 1, mThumbColor, 3);
seekBar.setTickNumb(mTickCount);
}
public void setOnRangeBarChangeListener(OnRangeSeekBarChangerListener onRangeBarChangeListener) {
mListener = onRangeBarChangeListener;
}
/**
* Set number of ticks
*
* #param tickCount Default is 100
*/
public void setTickCount(int tickCount) {
mTickCount = tickCount;
seekBar.setTickNumb(mTickCount);
invalidate();
}
/**
* Set thumb's color
*
* #param thumbColor Default is orange
*/
public void setThumbColor(int thumbColor) {
mThumbColor = thumbColor;
thumbPaint.setColor(mThumbColor);
invalidate();
}
/**
* Set thumb's normal radius
*
* #param thumbRadius Default is 6dp
*/
public void setThumbNormalRadius(float thumbRadius) {
mThumbNormalRadius = (int) (thumbRadius*getResources().getDisplayMetrics().density);
leftThumb.radius = mThumbNormalRadius;
rightThumb.radius = mThumbNormalRadius;
invalidate();
}
/**
* Set thumb's pressed radius
*
* #param thumbPressedRadius Default is 8dp
*/
public void setThumbPressedRadius(float thumbPressedRadius) {
mThumbPressedRadius = (int) (thumbPressedRadius*getResources().getDisplayMetrics().density);
leftThumb.pressedRadius = mThumbPressedRadius;
rightThumb.pressedRadius = mThumbPressedRadius;
invalidate();
}
/**
* Set index for the Left Thumb
*
* #param leftIndex Default is 0
*/
public void setLeftIndex(int leftIndex) {
if (leftIndex < 0) {
throw new IllegalArgumentException("Left index must be >= 0");
}
mLeftIndex = leftIndex;
leftThumb.setIndex(seekBar, mLeftIndex);
invalidate();
}
/**
* Set index for the Right thumb
*
* #param rightIndex Default is 99
*/
public void setRightIndex(int rightIndex) {
if (rightIndex > mTickCount) {
throw new IllegalArgumentException("Left index must be <= tick count");
}
mRightIndex = rightIndex;
leftThumb.setIndex(seekBar, mRightIndex);
invalidate();
}
/**
* Get left index
*
* #return int
*/
public int getLeftIndex() {
return mLeftIndex;
}
/**
* Get right index
*
* #return int
*/
public int getRightIndex() {
return mRightIndex;
}
/**
* Get number of tick
*
* #return int
*/
public int getTickCount() {
return mTickCount;
}
#Override
protected synchronized void onDraw(Canvas canvas) {
seekBar.draw(canvas, leftThumb, rightThumb);
leftThumb.draw(canvas);
rightThumb.draw(canvas);
if (pressedThumb != null && pressedThumb.isAnimating) {
invalidate();
}
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height, width;
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(heightSize, DEFAULT_HEIGHT);
} else {
height = DEFAULT_HEIGHT;
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
width = Math.min(widthSize, DEFAULT_WIDTH);
} else {
width = DEFAULT_WIDTH;
}
setMeasuredDimension(width, height);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressedThumb = checkThumbPressed(eventX, eventY);
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
pressedThumb.setPressed(true);
invalidate();
setPressed(true);
return true;
case MotionEvent.ACTION_MOVE:
onActionMove(eventX);
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
onActionUp();
break;
}
return super.onTouchEvent(event);
}
private void onActionUp() {
pressedThumb.onActionUp(seekBar);
invalidate();
}
private void onActionMove(float eventX) {
if (eventX >= seekBar.leftX && eventX <= seekBar.rightX) {
pressedThumb.x = eventX;
invalidate();
if (leftThumb.x > rightThumb.x) {
final Thumb temp = leftThumb;
leftThumb = rightThumb;
rightThumb = temp;
}
int leftIndex = seekBar.getNearestTick(leftThumb);
int rightIndex = seekBar.getNearestTick(rightThumb);
if (mLeftIndex != leftIndex || mRightIndex != rightIndex) {
mLeftIndex = leftIndex;
mRightIndex = rightIndex;
if (mListener != null) {
mListener.onIndexChange(this, mLeftIndex, mRightIndex);
}
}
}
}
private Thumb checkThumbPressed(float eventX, float eventY) {
Thumb result = null;
boolean isLeftThumbPressed = leftThumb.isInTargetZone(eventX, eventY);
boolean isRightThumbPressed = rightThumb.isInTargetZone(eventX, eventY);
if (isLeftThumbPressed && isRightThumbPressed) {
result = (eventX / getWidth() >= 0.5f) ? leftThumb : rightThumb;
} else if (isLeftThumbPressed) {
result = leftThumb;
} else if (isRightThumbPressed) {
result = rightThumb;
}
return result;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
leftThumb.x = (getPaddingLeft() + 20 + leftThumb.normalRadius / 2);
leftThumb.y = (h + getPaddingTop() + getPaddingBottom()) / 2;
rightThumb.y = leftThumb.y;
rightThumb.x = (w - getPaddingRight() - 20 - rightThumb.normalRadius / 2);
seekBar.leftX = leftThumb.x;
seekBar.rightX = rightThumb.x;
seekBar.y = leftThumb.y;
leftThumb.setIndex(seekBar, mLeftIndex);
rightThumb.setIndex(seekBar, mRightIndex);
}
#Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
SavedState state = new SavedState(super.onSaveInstanceState());
state.tickCount = mTickCount;
state.leftIndex = mLeftIndex;
state.rightIndex = mRightIndex;
state.thumbColor = mThumbColor;
state.thumbNormalRadius = mThumbNormalRadius;
state.thumbPressedRadius = mThumbPressedRadius;
bundle.putParcelable(SavedState.STATE,state);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
SavedState savedState = bundle.getParcelable(SavedState.STATE);
mTickCount = savedState.tickCount;
mThumbColor = savedState.thumbColor;
mThumbNormalRadius = savedState.thumbNormalRadius;
mThumbPressedRadius = savedState.thumbPressedRadius;
mLeftIndex = savedState.leftIndex;
mRightIndex = savedState.rightIndex;
super.onRestoreInstanceState(savedState.getSuperState());
return;
}
super.onRestoreInstanceState(SavedState.EMPTY_STATE);
}
public interface OnRangeSeekBarChangerListener {
void onIndexChange(RangeSeekBar rangeBar, int leftIndex, int rightIndex);
}
static class SavedState extends BaseSavedState {
static final String STATE = "RangeSeekBar.STATE";
int tickCount;
int leftIndex;
int rightIndex;
int thumbColor;
int thumbNormalRadius;
int thumbPressedRadius;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
}
public static final Creator<SavedState> CREATOR =
new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
I have created a CustomView for Calendar. I have an onDraw method to draw the text in the calendar. I want to change the color of the day Text when i click on it. How can i achieve it?
CalendarView.java :
package com.example.calendar_module;
import java.util.Calendar;
import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.MonthDisplayHelper;
import android.view.MotionEvent;
import android.widget.ImageView;
public class CalendarView extends ImageView {
private static int WEEK_TOP_MARGIN = 0;
private static int WEEK_LEFT_MARGIN = 05;
private static int CELL_WIDTH = 20;
private static int CELL_HEIGH = 20;
private static int CELL_MARGIN_TOP = 05;
private static int CELL_MARGIN_LEFT = 29;
private static float CELL_TEXT_SIZE;
private static int CALENDAR_WIDTH;
private static int CALENDAR_HEIGHT;
private static final String TAG = "CalendarView";
private String[] mDayString = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
private Calendar mRightNow = null;
private Drawable mWeekTitle = null;
private Cell mToday = null;
private Cell[][] mCells = new Cell[6][7];
private Cell[] mDayCells = new Cell[7];
private OnCellTouchListener mOnCellTouchListener = null;
MonthDisplayHelper mHelper;
Drawable mDecoration = null;
public interface OnCellTouchListener {
public void onTouch(Cell cell);
}
public CalendarView(Context context) {
this(context, null);
}
public CalendarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CalendarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDecoration = context.getResources().getDrawable(R.drawable.typeb_calendar_today);
initCalendarView();
}
private void initCalendarView() {
mRightNow = Calendar.getInstance();
// prepare static vars
Resources res = getResources();
WEEK_TOP_MARGIN = (int) res.getDimension(R.dimen.week_top_margin);
WEEK_LEFT_MARGIN = (int) res.getDimension(R.dimen.week_left_margin);
CELL_WIDTH = (int) res.getDimension(R.dimen.cell_width);
CELL_HEIGH = (int) res.getDimension(R.dimen.cell_heigh);
CELL_MARGIN_TOP = (int) res.getDimension(R.dimen.cell_margin_top);
CELL_MARGIN_LEFT = (int) res.getDimension(R.dimen.cell_margin_left);
// CALENDAR_HEIGHT = 700;
// CALENDAR_WIDTH = 700;
//
CALENDAR_HEIGHT = (int) res.getDimension(R.dimen.calendar_height);
CALENDAR_WIDTH = (int) res.getDimension(R.dimen.calendar_width);
System.out.println("Width and Hight :"+CALENDAR_WIDTH+" "+CALENDAR_HEIGHT);
System.out.println("Dimen Width and Height : "+R.dimen.calendar_width+" "+R.dimen.calendar_height);
CELL_TEXT_SIZE = res.getDimension(R.dimen.cell_text_size);
// set background
// setImageResource(R.drawable.background);
mWeekTitle = res.getDrawable(R.drawable.calendar_week);
mHelper = new MonthDisplayHelper(mRightNow.get(Calendar.YEAR), mRightNow.get(Calendar.MONTH));
}
private void initCells() {
class _calendar {
public int day;
public boolean thisMonth;
public _calendar(int d, boolean b) {
day = d;
thisMonth = b;
}
public _calendar(int d) {
this(d, false);
}
};
_calendar tmp[][] = new _calendar[6][7];
for(int i=0; i<tmp.length; i++) {
int n[] = mHelper.getDigitsForRow(i);
for(int d=0; d<n.length; d++) {
if(mHelper.isWithinCurrentMonth(i,d))
tmp[i][d] = new _calendar(n[d], true);
else
tmp[i][d] = new _calendar(n[d]);
}
}
Calendar today = Calendar.getInstance();
int thisDay = 0;
mToday = null;
if(mHelper.getYear()==today.get(Calendar.YEAR) && mHelper.getMonth()==today.get(Calendar.MONTH)) {
thisDay = today.get(Calendar.DAY_OF_MONTH);
}
// build cells
Rect Bound = new Rect(CELL_MARGIN_LEFT, CELL_MARGIN_TOP, CELL_WIDTH+CELL_MARGIN_LEFT, CELL_HEIGH+CELL_MARGIN_TOP);
// for( int i=0 ; i < 7 ; i++ )
// {
//
// mDayCells[i] = new Cell(mDayString[i],new Rect(Bound),CELL_TEXT_SIZE);
// Bound.offset(CELL_WIDTH, 0);
//
// }
//
// Bound.offset(0, CELL_HEIGH); // move to next row and first column
// Bound.left = CELL_MARGIN_LEFT;
// Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;
//
for(int week=0; week<mCells.length; week++) {
for(int day=0; day<mCells[week].length; day++)
{
if(tmp[week][day].thisMonth) {
if(day==0 || day==6 )
mCells[week][day] = new RedCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
else
mCells[week][day] = new Cell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
} else {
mCells[week][day] = new GrayCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
}
Bound.offset(CELL_WIDTH, 0); // move to next column
// get today
if(tmp[week][day].day==thisDay && tmp[week][day].thisMonth) {
mToday = mCells[week][day];
mDecoration.setBounds(mToday.getBound());
}
}
Bound.offset(0, CELL_HEIGH); // move to next row and first column
Bound.left = CELL_MARGIN_LEFT;
Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;
}
}
#Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
// Rect re = getDrawable().getBounds();
// WEEK_LEFT_MARGIN = CELL_MARGIN_LEFT = (right-left - re.width()) / 2;
// mWeekTitle.setBounds(WEEK_LEFT_MARGIN, WEEK_TOP_MARGIN, WEEK_LEFT_MARGIN+mWeekTitle.getMinimumWidth(), WEEK_TOP_MARGIN+mWeekTitle.getMinimumHeight());
initCells();
super.onLayout(changed, left, top, right, bottom);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
System.out.println("Width : "+CALENDAR_WIDTH);
System.out.println("Height : "+CALENDAR_HEIGHT);
setMeasuredDimension(CALENDAR_WIDTH, CALENDAR_HEIGHT);
// setMeasuredDimension(100,200);
}
public void setTimeInMillis(long milliseconds) {
mRightNow.setTimeInMillis(milliseconds);
initCells();
this.invalidate();
}
public int getYear() {
return mHelper.getYear();
}
public int getMonth() {
return mHelper.getMonth();
}
public void nextMonth() {
mHelper.nextMonth();
initCells();
invalidate();
}
public void previousMonth() {
mHelper.previousMonth();
initCells();
invalidate();
}
public boolean firstDay(int day) {
return day==1;
}
public boolean lastDay(int day) {
return mHelper.getNumberOfDaysInMonth()==day;
}
public void goToday() {
Calendar cal = Calendar.getInstance();
mHelper = new MonthDisplayHelper(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH));
initCells();
invalidate();
}
public Calendar getDate() {
return mRightNow;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mOnCellTouchListener!=null){
for(Cell[] week : mCells) {
for(Cell day : week) {
if(day.hitTest((int)event.getX(), (int)event.getY())) {
mOnCellTouchListener.onTouch(day);
}
}
}
}
return super.onTouchEvent(event);
}
public void setOnCellTouchListener(OnCellTouchListener p) {
mOnCellTouchListener = p;
}
#Override
protected void onDraw(Canvas canvas) {
// draw background
super.onDraw(canvas);
mWeekTitle.draw(canvas);
// draw cells
for(Cell[] week : mCells) {
for(Cell day : week) {
day.draw(canvas);
}
}
// draw today
if(mDecoration!=null && mToday!=null) {
mDecoration.draw(canvas);
}
}
public class GrayCell extends Cell {
public GrayCell(int dayOfMon, Rect rect, float s) {
super(dayOfMon, rect, s);
mPaint.setColor(Color.LTGRAY);
}
}
private class RedCell extends Cell {
public RedCell(int dayOfMon, Rect rect, float s) {
super(dayOfMon, rect, s);
mPaint.setColor(0xdddd0000);
}
}
}
Cell.java :
package com.example.calendar_module;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.Log;
public class Cell {
private static final String TAG = "Cell";
protected Rect mBound = null;
protected int mDayOfMonth = 1; // from 1 to 31
protected Paint mPaint = new Paint(Paint.SUBPIXEL_TEXT_FLAG
|Paint.ANTI_ALIAS_FLAG);
int dx, dy;
protected String mDayString;
private Cell cell ;
public Cell(int dayOfMon, Rect rect, float textSize, boolean bold) {
mDayOfMonth = dayOfMon;
mBound = rect;
mPaint.setTextSize(textSize);
mPaint.setColor(Color.BLACK);
if(bold) mPaint.setFakeBoldText(true);
dx = (int) mPaint.measureText(String.valueOf(mDayOfMonth)) / 2;
dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
}
public Cell(String day,Rect rect,float textSize,boolean bold)
{
mDayString = day;
mBound = rect;
mPaint.setTextSize(textSize);
mPaint.setColor(Color.BLACK);
if(bold) mPaint.setFakeBoldText(true);
dx = (int) mPaint.measureText(String.valueOf(mDayString)) / 2;
dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
}
public Cell(String day , Rect rect , float textSize , int newColor)
{
mDayString = day;
mBound = rect;
mPaint.setTextSize(textSize);
mPaint.setColor(newColor);
dx = (int) mPaint.measureText(String.valueOf(mDayString)) / 2;
dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
}
public Cell(int dayOfMon, Rect rect, float textSize) {
this(dayOfMon, rect, textSize, false);
}
public Cell(String day,Rect rect,float textSize)
{
this(day,rect,textSize,false);
}
protected void draw(Canvas canvas) {
canvas.drawText(String.valueOf(mDayOfMonth), mBound.centerX() - dx, mBound.centerY() + dy, mPaint);
}
public int getDayOfMonth() {
return mDayOfMonth;
}
public boolean hitTest(int x, int y) {
return mBound.contains(x, y);
}
public Rect getBound() {
return mBound;
}
public String toString() {
return String.valueOf(mDayOfMonth)+"("+mBound.toString()+")";
}
}
CalendarActivity.java
package com.example.calendar_module;
import java.util.GregorianCalendar;
import com.example.calendar_module.CalendarView.OnCellTouchListener;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.DateUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class CalendarActivity extends Activity{
public static final String MIME_TYPE = "vnd.android.cursor.dir/vnd.example.calendar_module.date";
public static String mClickedDate, mClickedMonth;
CalendarView mView = null;
TextView mHit;
Handler mHandler = new Handler();
private Button mNextButton;
private Button mPreviousButton;
private TextView mMonthText ;
private int mMonthInt;
private ListView mEventListView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mView = (CalendarView)findViewById(R.id.calendar);
mEventListView = (ListView) findViewById(R.id.EventsList);
mEventListView.setAdapter(new BadgeAdapter(this));
mView.setOnCellTouchListener(new OnCellTouchListener() {
#Override
public void onTouch(Cell cell) {
TextView mMonthText = (TextView)findViewById(R.id.MonthText);
mClickedDate = ""+cell.getDayOfMonth();
mClickedMonth =""+mMonthText.getText();
// System.out.println("Clicked date is : "+mClickedDate+" "+mClickedMonth);
// startActivity(new Intent(CalendarActivity.this,Event.class));
// cell = new Cell(cell.getDayOfMonth(),new Rect(cell.getBound()),Color.MAGENTA);
}
});
mNextButton = (Button) findViewById(R.id.NextMonth);
mPreviousButton = (Button) findViewById(R.id.PreviousMonth);
mMonthText = (TextView) findViewById(R.id.MonthText);
mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());
// System.out.println("CurrentMonth is : "+mView.getMonth());
// if(getIntent().getAction().equals(Intent.ACTION_PICK))
// findViewById(R.id.hint).setVisibility(View.INVISIBLE);
mNextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mView.nextMonth();
mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());
}
});
mPreviousButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
mView.previousMonth();
mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());
}
});
System.out.println("Calendar View Height : "+mView.getHeight());
}
private class RedCell extends Cell {
public RedCell(Cell cell) {
super(cell.getDayOfMonth(),new Rect(cell.getBound()), R.dimen.cell_text_size);
mPaint.setColor(Color.RED);
}
}
}
Call mView.invalidate(); in your onClick() method for that View. This will call onDraw() (eventually), which will then run the drawing code for your view.