package com.ijoomer.customviews;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.ijoomer.custom.interfaces.CustomSliderListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* This Class Contains All Method Related To CustomSliderView.
*
* @author tasol
*
*/
public class CustomSliderView extends FrameLayout implements OnTouchListener {
// The touch position relative to the slider view (ie: left=0, right=width of the slider view)
private float mTouchXPosition;
private float mTouchXPositionAfterResized;
private float mTouchXPositionForThumb;
// Images used for thumb and the bar
protected ImageView mThumbImageView, mSliderBarImageView;
protected Bitmap mThumbBitmap;
protected Bitmap mThumbBitmapResized;
protected Bitmap mSliderBarBitmap;
// These two variables are useful if you want to programatically reskin the slider
protected int mThumbResourceId;
protected int mSliderBarResourceId;
GestureDetector gestureDetector1;
View.OnTouchListener gestureListener;
// Default ranges
protected int mMinValue=0;
protected int mMaxValue=100;
protected int xDistance=0;
protected int xResizedDistance=0;
// protected int calculatedSizeOfThumb;
protected int calculatedSizeOfThumbResized;
protected boolean isTouchEvent = true;
protected boolean isMultiTouch = false;
// Used internally during touches event
protected float mTargetValue=0;
protected int mSliderLeftPosition, mSliderRightPosition;
protected ArrayList<Bitmap> allTracks;
// Holds the object that is listening to this slider.
protected OnTouchListener mDelegateOnTouchListener;
protected OnLongClickListener mDelegateOnLongListener;
protected int calculatedSizeOfThumb;
CustomSliderListener customSliderListener;
/**
* Default constructors.
* Just tell Android that we're doing custom drawing and that we want to listen to touch events.
*/
public CustomSliderListener getCustomSliderListener() {
return customSliderListener;
}
public void setCustomSliderListener(CustomSliderListener customSliderListener) {
this.customSliderListener = customSliderListener;
}
public CustomSliderView(Context context)
{
super(context);
setWillNotDraw(false);
setOnTouchListener(this);
}
public CustomSliderView(Context context, AttributeSet attrs)
{
super(context, attrs);
calculatedSizeOfThumbResized = 0;
setWillNotDraw(false);
setOnTouchListener(this);
}
public CustomSliderView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setWillNotDraw(false);
this.setOnTouchListener(this);
}
/*
* This should be called by the object that wants to listen to the touch events
*/
public void setDelegateOnTouchListener(OnTouchListener onTouchListener)
{
eventDataMap = new HashMap<Integer, EventData>();
mDelegateOnTouchListener=onTouchListener;
}
public void setDelegateOnLongListener(OnLongClickListener onLongListener)
{
mDelegateOnLongListener=onLongListener;
}
public boolean getEvent(){
return isTouchEvent;
}
public void setDistance(int xDistance){
this.xDistance = xDistance;
}
public void setResizedDistance(int xResizedDistance){
this.xResizedDistance = xResizedDistance;
}
public void setResourceIds(int thumbResourceId, int sliderBarResourceId)
{
mThumbResourceId=thumbResourceId;
mSliderBarResourceId=sliderBarResourceId;
mThumbImageView=null;
mSliderBarImageView=null;
}
String ItemId;
private float MIN_DISTANCE = 20;
private float downX;
/*
* This sets the range of the slider values. Eq: 0 to 100 or 20 to 70.
*/
public void setRange(int min, int max)
{
mMinValue=min;
mMaxValue=max;
}
/*
* This sets the value, between mMinValue and mMaxValue
*/
public void setScaledValue(int value)
{
mTargetValue=value;//((value-mMinValue)/range)*fillWidth;
invalidate();
}
/**
* @return The actual value of the thumb position, scaled to the min and max value
*/
public int getScaledValue()
{
return (int)mMinValue+(int)((mMaxValue-mMinValue)*getPercentValue());
}
/**
* @return The percent value of the current thumb position.
*/
public float getPercentValue()
{
float fillWidth=mSliderBarImageView.getWidth();
float relativeTouchX=mTouchXPosition-mSliderBarImageView.getLeft();
float percentage=relativeTouchX/fillWidth;
return percentage;
}
/**
*
* @param percentValue between 0 to 1.0f
*/
public void setPercentValue(float percentValue)
{
float position=mSliderLeftPosition+percentValue*(mSliderRightPosition-mSliderLeftPosition-mThumbBitmap.getWidth());
mTouchXPosition=position;
invalidate();
}
public void setTracks(ArrayList<Bitmap> arrayOfTracks){
allTracks = arrayOfTracks;
}
public void calculateLeftDistance(int distance){
if(xResizedDistance > 0 && xResizedDistance < xDistance){
if(calculatedSizeOfThumb== xDistance){
}else{
distance = xResizedDistance;
}
}else{
distance = xDistance;
}
if (mTouchXPosition < mSliderLeftPosition + distance){
if(!isTouchEvent){
mTouchXPosition=distance ;
}else{
mTouchXPositionForThumb = mSliderLeftPosition+distance - mTouchXPosition;
mTouchXPosition=distance - mTouchXPositionForThumb;
if(distance - mTouchXPosition > mSliderLeftPosition){
mTouchXPosition = distance;
}
}
}
}
@Override
protected void onDraw (Canvas canvas)
{
// Load the resources if not already loaded
if (mThumbImageView==null)
{
mThumbImageView=(ImageView)this.getChildAt(1);
this.removeView(mThumbImageView);
if (mThumbResourceId>0)
{
mThumbBitmap=BitmapFactory.decodeResource(getContext().getResources(), mThumbResourceId);
mThumbImageView.setImageBitmap(mThumbBitmap);
}
// USe the drawing cache so that we don't have to scale manually.
mThumbImageView.setDrawingCacheEnabled(true);
mThumbBitmap = mThumbImageView.getDrawingCache(true);
mThumbBitmapResized = mThumbImageView.getDrawingCache(true);
}
if (mSliderBarImageView==null)
{
try{
mSliderBarImageView=(ImageView)this.getChildAt(0);
this.removeView(mSliderBarImageView);
// If user has specified a different skin, load it
if (mSliderBarResourceId>0)
{
mSliderBarBitmap=BitmapFactory.decodeResource(getContext().getResources(), mSliderBarResourceId);
mSliderBarImageView.setImageBitmap(mSliderBarBitmap);
}
// USe the drawing cache so that we don't have to scale manually.
mSliderBarImageView.setDrawingCacheEnabled(true);
mSliderBarBitmap = mSliderBarImageView.getDrawingCache(true);
//mSliderBarImageView.setDrawingCacheEnabled(false);
mSliderLeftPosition=mSliderBarImageView.getLeft();
mSliderRightPosition=mSliderBarImageView.getLeft()+mSliderBarBitmap.getWidth();
}catch (Exception e) {
e.printStackTrace();
}
}
// Adjust thumb position (this handles the case where setScaledValue() was called)
if (mTargetValue>0)
{
float fillWidth=mSliderBarImageView.getMeasuredWidth();
float range=(mMaxValue-mMinValue);
mTouchXPosition=((mTargetValue-mMinValue)/range)*fillWidth;
mTargetValue=0;
}
// Don't allow going out of bounds
if(isMultiTouch){
calculateLeftDistance(xResizedDistance);
}else{
calculateLeftDistance(xDistance);
}
if (mTouchXPosition>mSliderRightPosition)
mTouchXPosition=mSliderRightPosition;
if (mSliderBarBitmap!=null)
if (mThumbBitmap!=null)
{
writeOnDrawable(canvas);
if(isMultiTouch){
int i = 0;
float startingPointOfThumb = 0;
float endingPointOfThumb = 0;
for(EventData event : eventDataMap.values())
{
if(i==0){
startingPointOfThumb = event.x;
}
if(i==1){
endingPointOfThumb = event.x;
}
i++;
}
if(endingPointOfThumb >0){
if(endingPointOfThumb>startingPointOfThumb){
calculatedSizeOfThumb = (int) (endingPointOfThumb - startingPointOfThumb);
if(calculatedSizeOfThumbResized>0){
mThumbBitmap = mThumbBitmapResized;
}else{
calculatedSizeOfThumbResized = calculatedSizeOfThumb;
}
}else{
calculatedSizeOfThumb = (int) (startingPointOfThumb - endingPointOfThumb);
if(calculatedSizeOfThumbResized>0){
mThumbBitmap = mThumbBitmapResized;
}else{
calculatedSizeOfThumbResized = calculatedSizeOfThumb;
}
}
}
if(calculatedSizeOfThumb>0 && calculatedSizeOfThumb < xDistance){
Bitmap n = Bitmap.createScaledBitmap(mThumbBitmap,calculatedSizeOfThumb,mThumbBitmap.getHeight() ,true);
mThumbBitmap = n;
if(customSliderListener!=null){
customSliderListener.onThumbSizeChanged(calculatedSizeOfThumb);
if(mTouchXPosition > mSliderRightPosition - mThumbBitmap.getWidth()){
canvas.drawBitmap(n , (mTouchXPosition - mThumbBitmap.getWidth()),0, null);
}else{
canvas.drawBitmap(n , (mTouchXPosition),0, null);
}
}
}else{
calculatedSizeOfThumb = xDistance;
canvas.drawBitmap(mThumbBitmap , mTouchXPosition-mThumbBitmap.getWidth(),0, null);
}
}else{
if(mTouchXPosition-mThumbBitmap.getWidth() == 0){
if(!isTouchEvent){
canvas.drawBitmap(mThumbBitmap , mTouchXPosition-mThumbBitmap.getWidth(),0, null);
}else{
if(mTouchXPositionAfterResized > mSliderRightPosition - xDistance){
canvas.drawBitmap(mThumbBitmap , mTouchXPositionAfterResized/2,0, null);
}else{
canvas.drawBitmap(mThumbBitmap , mTouchXPositionAfterResized,0, null);
}
}
}else{
canvas.drawBitmap(mThumbBitmap , mTouchXPosition-mThumbBitmap.getWidth(),0, null);
}
}
}
}
@SuppressWarnings("deprecation")
public BitmapDrawable writeOnDrawable(Canvas canvas){
Bitmap newBitmap = null;
try {
newBitmap = Bitmap.createBitmap(mThumbBitmap.getWidth(),mThumbBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Paint p = new Paint();
int x = 0;
int y = 5;
for(int i=0;i<allTracks.size();i++){
Bitmap n = Bitmap.createScaledBitmap(allTracks.get(i),80,60,true);
canvas.drawBitmap(n,x,y, p);
x = x+40;
}
} catch (Exception e) {
e.printStackTrace();
}
return new BitmapDrawable(newBitmap);
}
private float pressureAmplification = (float) DefaultValues.PressureAmplificaton;
private Map<Integer, EventData> eventDataMap;
private class EventData{
public float x;
}
public class DefaultValues {
public final static float TouchCircleRadius = (float) 5.0;
public final static float PressureRingOffset = (float) 1.0;
public final static float PressureAmplificaton = (float) 3.0;
public final static int PauseUIThread = 1000;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
int action = event.getActionMasked();
int pointerIndex = event.getActionIndex();
int pointerId = event.getPointerId(pointerIndex);
EventData eventData = null ;
switch (action) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
isTouchEvent = true;
mTouchXPosition=event.getX();
mTouchXPositionAfterResized = event.getX();
eventData = new EventData();
eventData.x = event.getX(pointerIndex);
eventDataMap.put(new Integer(pointerId), eventData);
return true;
case MotionEvent.ACTION_POINTER_DOWN:
downX = event.getX();
mTouchXPosition=event.getX();
mTouchXPositionAfterResized = event.getX();
isTouchEvent = true;
isMultiTouch = true;
eventData = new EventData();
eventData.x = event.getX(pointerIndex);
eventDataMap.put(new Integer(pointerId), eventData);
return true;
case MotionEvent.ACTION_MOVE:
isTouchEvent = false;
for(int i = 0; i < event.getPointerCount(); i++)
{
int curPointerId = event.getPointerId(i);
if(eventDataMap.containsKey(new Integer(curPointerId)))
{
EventData moveEventData = eventDataMap.get(new Integer(curPointerId));
moveEventData.x = event.getX(i);
try{
float calculateDistance = downX < event.getX() ? event.getX() - downX : downX - event.getX();
if((int)(calculateDistance) > MIN_DISTANCE ){
mTouchXPosition=event.getX();
mTouchXPositionAfterResized = event.getX();
isTouchEvent = false;
invalidate();
if (mDelegateOnTouchListener!=null){
mDelegateOnTouchListener.onTouch(view, event);
}
}else{
}
}catch (Throwable e) {
e.printStackTrace();
}
}
}
eventData = new EventData();
eventData.x = event.getX(pointerIndex);
eventDataMap.put(new Integer(pointerId), eventData);
mTouchXPosition=event.getX();
return false;
case MotionEvent.ACTION_UP:
isTouchEvent = true;
isMultiTouch = false;
eventDataMap.remove(new Integer(pointerId));
mTouchXPosition=event.getX();
if (mDelegateOnTouchListener!=null)
mDelegateOnTouchListener.onTouch(view, event);
return true;
case MotionEvent.ACTION_POINTER_UP:
eventDataMap = new HashMap<Integer, EventData>();
isMultiTouch = false;
isTouchEvent = true;
eventDataMap.remove(new Integer(pointerId));
return true;
case MotionEvent.ACTION_OUTSIDE:
break;
}
return false;
}
}