I need help with my game!
I am drawing my playermodel with a bitmap and I want to change the model with an ontouch event, but it is not working and I don't know, what I'm doing wrong: (
First of all here is my playerclass were I'm creating the bitmap:
public class Player extends GameObject{
private Bitmap spritesheet;
private String scoreText;
public int score;
private double dya;
private boolean up;
private boolean playing;
private Animation animation = new Animation();
private long startTime;
public boolean jumpable = false;
public boolean jumphigh;
public boolean falldown;
private int boden;
private boolean sliden;
public Player(Bitmap res, int w, int h, int numFrames) {
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 +26 ;
//y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
height = h;
width = w;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100;
Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;
for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}
animation.setFrames(image);
animation.setDelay(40);
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update()
{
//score
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
score = score+7;
startTime = System.nanoTime();
scoreText = ""+score ;
}
animation.update();
if(up == true && jumpable == true){
jumphigh = true;
// dy = -5;
// System.out.println(up);
}else{
jumphigh = false;
}
if (jumphigh == true){
dy = -5;
}
if (falldown == true){
dy = 5;
}
if(dy>14)dy = 14;
if(dy<-14)dy = -14;
y += dy*2;
if (y >= boden){
y = boden;
jumpable = true;
falldown = false;
dy = 0;
}else if (y <= 60){
y= 60;
up = false ;
jumphigh = false;
falldown = true;
dy = 0;
}
if (y < GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100){
jumpable = false;
}
}
public void restart(){
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(animation.getImage(),x,y,null);
Paint paint = new Paint();
paint.setTypeface(Typeface.create(Typeface.SANS_SERIF,Typeface.NORMAL));
paint.setColor(Color.BLACK);
paint.setTextSize(50);
canvas.drawText(scoreText, 50 , 50 , paint);
}
public void setY(Canvas canvas){
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
draw(canvas);
}
public int getScore(){return score;}
public void setSliden() {sliden = true; }
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetP(){ x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;}
public void resetDYA(){dya = 0;}
public void resetScore(){score = 0;}
And here is my gamepanel code where I'm calling my bitmap ( I give you only the parts you need for this question):
private Player player;
private int PlayerSprite = R.drawable.test;;
private int Playerhight = 120;
private int Playerwight = 115;
private int PlayerFrames = 8;
#Override
public void surfaceCreated(SurfaceHolder holder) {
player = new Player(BitmapFactory.decodeResource(getResources(), PlayerSprite), Playerwight, Playerhight, PlayerFrames);
invalidate();
thread.setRunning(true);
thread.start();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
PlayerSprite = R.drawable.sliden;
Playerhight = 52;
Playerwight = 130;
PlayerFrames = 1;
return true;
}
if(event.getAction()==MotionEvent.ACTION_UP)
{
player.setUp(false);
PlayerSprite = R.drawable.test;
Playerhight = 120;
Playerwight = 115;
PlayerFrames = 8;
return true;
}
return super.onTouchEvent(event);
}
public void update() {
if (player.getPlaying() == true && State == STATE.INGAME) {
player.update();
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
final float scaleFactorX = getWidth() / (WIDTH*1.f);
final float scaleFactorY = getHeight() / (HEIGHT*1.f);
if (canvas != null && State == STATE.INGAME) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
player.draw(canvas);
canvas.restoreToCount(savedState);
invalidate();
}
}
I want just want to change the image of the player with a onTouch event and its just not working.
Just call invalidate() in onTouchEvent(MotionEvent event)() and see the change.
Do not call invalidate in onDraw(), it will cause the permanent loop and reduce the performance of your app.
I have a custom View and I wonder, is there any chace that I could detect if something outside of my View is clicked. It MUST be in the View class, or else it can not work as I intended it to!
Full file: https://github.com/Nicba1010/AndroidLibrary/blob/master/src/com/nicba1010/utils/views/PieChartView.java
OnTouchEvent(so you know I did something)
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
selected = null;
invalidate();
return true;
}
double deltaX = event.getX() - rect.width() / 2 - rect.left;
double deltaY = -(event.getY() - rect.height() / 2 - rect.top);
double fromMid = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
boolean inCircle = fromMid < (rectSelect.bottom / 2);
if (inCircle) {
double angleInDegrees = getPositionOnCircumference(deltaX, deltaY);
float percentage = (float) (angleInDegrees / 360f);
float totalPerc = 0;
int index = -1, i = 0;
for (PieChartSlice e : slices) {
if (percentage > totalPerc) {
index = i;
} else if (percentage < totalPerc) {
break;
}
totalPerc += e.getPercentage();
i++;
}
if (index == -1) {
Toast.makeText(getContext(), "ERROR", Toast.LENGTH_LONG).show();
} else {
final PieChartSlice tmp = slices.get(index);
addScaleTask(rect, 500, 0.9f, new Runnable() {
#Override
public void run() {
selected = tmp;
}
});
selected = slices.get(index);
invalidate();
Toast.makeText(getContext(), selected.getName(),
Toast.LENGTH_SHORT).show();
onSliceSelectedListener.onSliceSelected(this, selected);
}
} else {
if (selected != null) {
addScaleTask(rect, 500, 1f, new Runnable() {
#Override
public void run() {
selected = null;
}
});
invalidate();
}
}
return super.onTouchEvent(event);
}
View has the getHitRect(Rect) method. You can use to retrieve it hit rect of this view and you can use this rect to check it the MotionEvent it is inside it. For instance
Rect rect = new Rect();
getHitRect(rect);
if (rect.contains((int) event.getX(), (int) event.getY()) {
}
I have drawn a Cubic Curve on canvas using
myPath.cubicTo(10, 10, w, h/2, 10, h-10);
I have four ImageView on that screen and I want to move that ImageViews on the drawn curve when I drag that image with touch.
I have referred the links :
Move Image on Curve Path
Move object on Curve
Move imageview on curve
What I get is, Animation to move the Image on Curve with the duration defined by t.
But I want to move that ImageView on touch in direction of that curve area only.
Following is my Screen :
So, I want all the (x,y) co-ordinates of the curve to move ImageView on that curve only.
Else I want an equation to draw a curve so that I can interpolate x value for the touched y value.
I have goggled a lot but didn't succeed.
Any advice or guidance will help me a lot.
Approach
I would suggest a different approach than using bezier as you would need to reproduce the math for it in order to get the positions.
By using simple trigonometry you can achieve the same visual result but in addition have full control of the positions.
Trigonometry
For example:
THIS ONLINE DEMO produces this result (simplified version for sake of demo):
Define an array with the circles and angle positions instead of y and x positions. You can filter angles later if they (e.g. only show angles between -90 and 90 degrees).
Using angles will make sure they stay ordered when moved.
var balls = [-90, -45, 0, 45]; // example "positions"
To replace the Bezier curve you can do this instead:
/// some setup variables
var xCenter = -80, /// X center of circle
yCenter = canvas.height * 0.5, /// Y center of circle
radius = 220, /// radius of circle
x, y; /// to calculate line position
/// draw half circle
ctx.arc(xCenter, yCenter, radius, 0, 2 * Math.PI);
ctx.stroke();
Now we can use an Y value from mouse move/touch etc. to move around the circles:
/// for demo, mousemove - adopt as needed for touch
canvas.onmousemove = function(e) {
/// get Y position which is used as delta to angle
var rect = demo.getBoundingClientRect();
dlt = e.clientY - rect.top;
/// render the circles in new positions
render();
}
The rendering iterates through the balls array and render them in their angle + delta:
for(var i = 0, angle; i < balls.length; i++) {
angle = balls[i];
pos = getPosfromAngle(angle);
/// draw circles etc. here
}
The magic function is this:
function getPosfromAngle(a) {
/// get angle from circle and add delta
var angle = Math.atan2(delta - yCenter, radius) + a * Math.PI / 180;
return [xCenter + radius * Math.cos(angle),
yCenter + radius * Math.sin(angle)];
}
radius is used as a pseudo position. You can replace this with an actual X position but is frankly not needed.
In this demo, to keep it simple, I have only attached mouse move. Move the mouse over the canvas to see the effect.
As this is demo code it's not structured optimal (separate render of background and the circles etc.).
Feel free to adopt and modify to suit your needs.
This code I have used to achieve this functionality and it works perfect as per your requirement...
public class YourActivity extends Activity {
private class ButtonInfo {
public Button btnObj;
public PointF OrigPos;
public double origAngle;
public double currentAngle;
public double minAngle;
public double maxAngle;
boolean isOnClick = false;
}
private int height;
private double radius;
private PointF centerPoint;
private final int NUM_BUTTONS = 4;
private final int FIRST_INDEX = 0;
private final int SECOND_INDEX = 1;
private final int THIRD_INDEX = 2;
private final int FORTH_INDEX = 3;
private final String FIRST_TAG = "FiRST_BUTTON";
private final String SECOND_TAG = "SECOND_BUTTON";
private final String THIRD_TAG = "THIRD_BUTTON";
private final String FORTH_TAG = "FORTH_BUTTON";
private boolean animInProgress = false;
private int currentButton = -1;
private ButtonInfo[] buttonInfoArray = new ButtonInfo[NUM_BUTTONS];
private int curveImageResource = -1;
private RelativeLayout parentContainer;
private int slop;
private boolean initFlag = false;
private int touchDownY = -1;
private int touchDownX = -1;
private int animCount;
private Context context;
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.fadeinleft, R.anim.fadeoutleft);
// hide action bar in view
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
Thread.setDefaultUncaughtExceptionHandler(
new MyDefaultExceptionHandler(this, getLocalClassName()));
setContentView(R.layout.your_layout);
context = this;
final ImageView curve_image = (ImageView) findViewById(R.id.imageView1);
parentContainer = (RelativeLayout) findViewById(R.id.llView);
// Set buttons on their location
for (int i = 0; i < NUM_BUTTONS; i++) {
buttonInfoArray[i] = new ButtonInfo();
}
Button img1 = (Button) findViewById(R.id.button_option1);
Button img2 = (Button) findViewById(R.id.button_option2);
Button img3 = (Button) findViewById(R.id.button_option3);
Button img4 = (Button) findViewById(R.id.button_option4);
//1st button
buttonInfoArray[FIRST_INDEX].btnObj = (Button) this
.findViewById(R.id.setting_button_option);
buttonInfoArray[FIRST_INDEX].btnObj.setTag(FIRST_TAG);
// 2nd button
buttonInfoArray[SECOND_INDEX].btnObj = (Button) this
.findViewById(R.id.scanning_button_option);
buttonInfoArray[SECOND_INDEX].btnObj.setTag(SECOND_TAG);
// 3rd button
buttonInfoArray[THIRD_INDEX].btnObj = (Button) this
.findViewById(R.id.manual_button_option);
buttonInfoArray[THIRD_INDEX].btnObj.setTag(THIRD_TAG);
// 4th button
buttonInfoArray[FORTH_INDEX].btnObj = (Button) this
.findViewById(R.id.logout_button_option);
buttonInfoArray[FORTH_INDEX].btnObj.setTag(FORTH_TAG);
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
currentButtonInfo.btnObj.setClickable(false);
}
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
currentButtonInfo.btnObj.bringToFront();
}
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
ViewTreeObserver vtoLayout = parentContainer.getViewTreeObserver();
vtoLayout.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (initFlag == true)
return;
centerPoint = new PointF(0, (parentContainer.getHeight()) / 2);
curve_image.setImageResource(curveImageResource);
ViewTreeObserver vtoCurveImage = curve_image
.getViewTreeObserver();
vtoCurveImage
.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (initFlag == true)
return;
ViewConfiguration vc = ViewConfiguration.get(parentContainer
.getContext());
slop = vc.getScaledTouchSlop();
parentContainer.setOnTouchListener(tlobj);
height = curve_image.getMeasuredHeight();
curve_image.getMeasuredWidth();
radius = (height / 2);
double angleDiff = Math.PI / (NUM_BUTTONS + 1);
double initialAngle = (Math.PI / 2 - angleDiff);
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
currentButtonInfo.origAngle = initialAngle;
initialAngle -= angleDiff;
}
double tempCurrentAngle;
double maxAngle = (-1 * Math.PI / 2);
tempCurrentAngle = maxAngle;
for (int i = NUM_BUTTONS - 1; i >= 0; i--) {
buttonInfoArray[i].maxAngle = tempCurrentAngle;
int buttonHeight = buttonInfoArray[i].btnObj
.getHeight();
if (buttonHeight < 30) {
buttonHeight = 80;
}
tempCurrentAngle = findNextMaxAngle(
tempCurrentAngle,
(buttonHeight + 5));
}
double minAngle = (Math.PI / 2);
tempCurrentAngle = minAngle;
for (int i = 0; i < NUM_BUTTONS; i++) {
buttonInfoArray[i].minAngle = tempCurrentAngle;
int buttonHeight = buttonInfoArray[i].btnObj
.getHeight();
if (buttonHeight < 30) {
buttonHeight = 80;
}
tempCurrentAngle = findNextMinAngle(
tempCurrentAngle, (buttonHeight + 5));
}
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
PointF newPos = getPointByAngle(currentButtonInfo.origAngle);
currentButtonInfo.OrigPos = newPos;
currentButtonInfo.currentAngle = currentButtonInfo.origAngle;
setTranslationX(
currentButtonInfo.btnObj,
(int) currentButtonInfo.OrigPos.x - 50);
setTranslationY(
currentButtonInfo.btnObj,
(int) currentButtonInfo.OrigPos.y - 50);
currentButtonInfo.btnObj.requestLayout();
}
initFlag = true;
}
});
}
});
}
/**
* Find next max angle
* #param inputAngle
* #param yDist
* #return
*/
private double findNextMaxAngle(double inputAngle, int yDist) {
float initYPos = (float) (centerPoint.y - (Math.sin(inputAngle) * radius));
float finalYPos = initYPos - yDist;
float finalXPos = getXPos(finalYPos);
double newAngle = getNewAngle(new PointF(finalXPos, finalYPos));
return newAngle;
}
/**
* Find next min angle
* #param inputAngle
* #param yDist
* #return
*/
private double findNextMinAngle(double inputAngle, int yDist) {
float initYPos = (int) (centerPoint.y - (Math.sin(inputAngle) * radius));
float finalYPos = initYPos + yDist;
float finalXPos = getXPos(finalYPos);
double newAngle = getNewAngle(new PointF(finalXPos, finalYPos));
return newAngle;
}
/**
* Apply reset transformation when user release touch
* #param buttonInfoObj
*/
public void applyResetAnimation(final ButtonInfo buttonInfoObj) {
ValueAnimator animator = ValueAnimator.ofFloat(0, 1); // values from 0
// to 1
animator.setDuration(1000); // 5 seconds duration from 0 to 1
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = ((Float) (animation.getAnimatedValue()))
.floatValue();
// Set translation of your view here. Position can be calculated
// out of value. This code should move the view in a half
// circle.
double effectiveAngle = buttonInfoObj.origAngle
+ ((buttonInfoObj.currentAngle - buttonInfoObj.origAngle) * (1.0 - value));
PointF newPos = getPointByAngle(effectiveAngle);
setTranslationX(buttonInfoObj.btnObj, newPos.x - 50);
setTranslationY(buttonInfoObj.btnObj, newPos.y - 50);
}
});
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
animCount++;
if (animCount == NUM_BUTTONS) {
animCount = 0;
currentButton = -1;
animInProgress = false;
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
setTranslationX(currentButtonInfo.btnObj,
currentButtonInfo.OrigPos.x - 50);
setTranslationY(currentButtonInfo.btnObj,
currentButtonInfo.OrigPos.y - 50);
currentButtonInfo.isOnClick = false;
currentButtonInfo.currentAngle = currentButtonInfo.origAngle;
currentButtonInfo.btnObj.setPressed(false);
currentButtonInfo.btnObj.requestLayout();
}
}
}
});
animator.start();
}
/**
* On Touch start animation
*/
private OnTouchListener tlobj = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent motionEvent) {
switch (MotionEventCompat.getActionMasked(motionEvent)) {
case MotionEvent.ACTION_MOVE:
if (currentButton < 0) {
return false;
}
if (animInProgress == true) {
return true;
}
float delta_y = motionEvent.getRawY() - touchDownY;
float delta_x = motionEvent.getRawX() - touchDownX;
updateButtonPos(new PointF((int) delta_x, (int) delta_y));
if (Math.abs(delta_x) > slop || Math.abs(delta_y) > slop) {
buttonInfoArray[currentButton].isOnClick = false;
parentContainer.requestDisallowInterceptTouchEvent(true);
}
return true;
case MotionEvent.ACTION_UP:
animCount = 0;
if (currentButton < 0) {
return false;
}
if(animInProgress == true) {
return true;
}
animInProgress = true;
for (ButtonInfo currentButtonInfo : buttonInfoArray) {
applyResetAnimation(currentButtonInfo);
if (currentButtonInfo.isOnClick) {
// TODO onClick code
String currentTag = (String) currentButtonInfo.btnObj.getTag();
if(currentTag.equalsIgnoreCase(FIRST_TAG)) {
//handle first button click
} else if(currentTag.equalsIgnoreCase(SECOND_TAG)) {
//handle second button click
} else if(currentTag.equalsIgnoreCase(THIRD_TAG)) {
//handle third button click
} else if(currentTag.equalsIgnoreCase(FORTH_TAG)) {
//handle forth button click
}
}
}
return true;
case MotionEvent.ACTION_DOWN:
if (currentButton >= 0) {
return false;
}
if (animInProgress == true) {
return true;
}
animCount = 0;
int buttonIndex = 0;
for (buttonIndex = 0; buttonIndex < NUM_BUTTONS; buttonIndex++) {
final ButtonInfo currentButtonInfo = buttonInfoArray[buttonIndex];
if (isRectHit(currentButtonInfo.btnObj, motionEvent,
currentButtonInfo.OrigPos)) {
currentButton = buttonIndex;
touchDownX = (int) motionEvent.getRawX();
touchDownY = (int) motionEvent.getRawY();
currentButtonInfo.isOnClick = true;
currentButtonInfo.btnObj.setPressed(true);
break;
}
}
if (buttonIndex == NUM_BUTTONS) {
currentButton = -1;
}
break;
default:
break;
}
return false;
}
};
/**
* Get X POS
* #param yPos
* #return
*/
public float getXPos(float yPos) {
float xPos = (float) (centerPoint.x
+ Math.sqrt((radius * radius)
- ((yPos - centerPoint.y) * (yPos - centerPoint.y))));
return xPos;
}
/**
* Get YPos based on X
* #param xPos
* #param isPositive
* #return
*/
public float getYPos(float xPos, boolean isPositive) {
if (isPositive)
return (float) (centerPoint.y - Math.sqrt((radius * radius)
- ((xPos - centerPoint.x) * (xPos - centerPoint.x))));
else
return (float) (centerPoint.y + Math.sqrt((radius * radius)
- ((xPos - centerPoint.x) * (xPos - centerPoint.x))));
}
/**
* Get New angle from define point
* #param newPoint
* #return
*/
private double getNewAngle(PointF newPoint) {
double deltaY = newPoint.y - centerPoint.y;
double deltaX = newPoint.x - centerPoint.x;
double newPointAngle = Math.atan(-1.0 * deltaY / deltaX);
return newPointAngle;
}
/**
* get Point By Angle
* #param angle
* #return
*/
private PointF getPointByAngle(double angle) {
PointF newPos;
double newX = centerPoint.x + Math.cos(angle) * radius;
double newY = (centerPoint.y) - (Math.sin(angle) * radius);
newPos = new PointF((int) newX, (int) newY);
return newPos;
}
/**
* Set new location for passed button
* #param currentButtonIndex
* #param effectiveDelta
* #param percentageCompleted
* #return
*/
private double updateControl(int currentButtonIndex, PointF effectiveDelta,
double percentageCompleted) {
PointF newPos = new PointF();
StringBuilder s1 = new StringBuilder();
double maxAngleForCurrentButton = buttonInfoArray[currentButtonIndex].maxAngle;
double minAngleForCurrentButton = buttonInfoArray[currentButtonIndex].minAngle;
double targetAngleForCurrentButton;
if (effectiveDelta.y > 0) {
targetAngleForCurrentButton = maxAngleForCurrentButton;
} else {
targetAngleForCurrentButton = minAngleForCurrentButton;
}
if (percentageCompleted == -1) {
boolean isYDisplacement = effectiveDelta.y > effectiveDelta.x ? true
: false;
isYDisplacement = true;
if (isYDisplacement) {
float newY = buttonInfoArray[currentButtonIndex].OrigPos.y
+ effectiveDelta.y;
if (newY > (centerPoint.y) + (int) radius) {
newY = (centerPoint.y) + (int) radius;
} else if (newY < (centerPoint.y) - (int) radius) {
newY = (centerPoint.y) - (int) radius;
}
float newX = getXPos(newY);
newPos = new PointF(newX, newY);
s1.append("isYDisplacement true : ");
}
} else {
double effectiveAngle = buttonInfoArray[currentButtonIndex].origAngle
+ ((targetAngleForCurrentButton - buttonInfoArray[currentButtonIndex].origAngle) * percentageCompleted);
newPos = getPointByAngle(effectiveAngle);
s1.append("percentage completed : " + percentageCompleted + " : "
+ effectiveAngle);
}
double newAngle = getNewAngle(newPos);
// For angle, reverse condition, because in 1st quarter, it is +ve, in
// 4th quarter, it is -ve.
if (newAngle < maxAngleForCurrentButton) {
newAngle = maxAngleForCurrentButton;
newPos = getPointByAngle(newAngle);
s1.append("max angle : " + newAngle);
}
if (newAngle > minAngleForCurrentButton) {
newAngle = minAngleForCurrentButton;
newPos = getPointByAngle(newAngle);
s1.append("min angle : " + newAngle);
}
setTranslationX(buttonInfoArray[currentButtonIndex].btnObj,
newPos.x - 50);
setTranslationY(buttonInfoArray[currentButtonIndex].btnObj,
newPos.y - 50);
return newAngle;
}
/**
* Set button Position
* #param deltaPoint
*/
public void updateButtonPos(PointF deltaPoint) {
for (int buttonIndex = 0; buttonIndex < NUM_BUTTONS; buttonIndex++) {
if (currentButton == buttonIndex) {
buttonInfoArray[buttonIndex].currentAngle = updateControl(
buttonIndex, deltaPoint, -1);
double targetAngleForCurrentButton;
if (deltaPoint.y > 0) {
targetAngleForCurrentButton = buttonInfoArray[buttonIndex].maxAngle;
} else {
targetAngleForCurrentButton = buttonInfoArray[buttonIndex].minAngle;
}
double percentageCompleted = (1.0 * (buttonInfoArray[buttonIndex].currentAngle - buttonInfoArray[buttonIndex].origAngle))
/ (targetAngleForCurrentButton - buttonInfoArray[buttonIndex].origAngle);
for (int innerButtonIndex = 0; innerButtonIndex < NUM_BUTTONS; innerButtonIndex++) {
if (innerButtonIndex == buttonIndex)
continue;
buttonInfoArray[innerButtonIndex].currentAngle = updateControl(
innerButtonIndex, deltaPoint, percentageCompleted);
}
break;
}
}
}
/**
* Find whether touch in button's rectanlge or not
* #param v
* #param rect
*/
private static void getHitRect(View v, Rect rect) {
rect.left = (int) com.nineoldandroids.view.ViewHelper.getX(v);
rect.top = (int) com.nineoldandroids.view.ViewHelper.getY(v);
rect.right = rect.left + v.getWidth();
rect.bottom = rect.top + v.getHeight();
}
private boolean isRectHit(View viewObj, MotionEvent motionEvent,
PointF viewOrigPos) {
Rect outRect = new Rect();
int x = (int) motionEvent.getX();
int y = (int) motionEvent.getY();
getHitRect(viewObj, outRect);
if (outRect.contains(x, y)) {
return true;
} else {
return false;
}
}
/**
* On Finish update transition
*/
#Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.activityfinishin, R.anim.activityfinishout);
}
/**
* On Native Back Pressed
*/
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
please tell me how can i remove the exception. or give me idea to implement zoom view with curlview.....
my xml file is like this,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relat">
<com.example.image.ZoomView
>
<com.example.image.PageCurlView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/dcgpagecurlPageCurlView1"
>
</com.example.image.PageCurlView>
my java file is
package com.example.image;
public class StandaloneExample extends Activity {
Button bt;LinearLayout lr;
/** Decoded bitmap image */
private Bitmap mBitmap;
private ZoomView zoomview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.standalone_example);
View v1 = ((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.standalone_example, null, false);
v1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
zoomview.addView(v1);
lr = (LinearLayout) findViewById(R.id.relat);
lr.addView(zoomview);
}
#Override
public void onDestroy(){
super.onDestroy();
System.gc();
finish();
}
public void lockOrientationLandscape() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
public void lockOrientationPortrait() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public void lockOrientation( int orientation ) {
setRequestedOrientation(orientation);
}
}
i have implemented zoomView.java as described in a link
pagecurlview.java class is
public class PageCurlView extends View {
private final static String TAG = "PageCurlView";
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
private int mCurlSpeed;
private int mUpdateRate;
private int mInitialEdgeOffset;
private int mCurlMode;
public static final int CURLMODE_SIMPLE = 0;
public static final int CURLMODE_DYNAMIC = 1;
private boolean bEnableDebugMode = false;
private WeakReference<Context> mContext;
private FlipAnimationHandler mAnimationHandler;
private float mFlipRadius;
private Vector2D mMovement;
private Vector2D mFinger;
private Vector2D mOldMovement;
private Paint mCurlEdgePaint;
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
private int mCurrentLeft, mCurrentTop;
private boolean bViewDrawn;
private boolean bFlipRight;
private boolean bFlipping;
private boolean bUserMoves;
private boolean bBlockTouchInput = false;
private boolean bEnableInputAfterDraw = false;
private Bitmap mForeground;
private Bitmap mBackground;
private ArrayList<Bitmap> mPages;
private int mIndex = 0;
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D a, Vector2D b) {
return a.cross(b);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
class FlipAnimationHandler extends Handler {
#Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
public PageCurlView(Context context) {
super(context);
init(context);
ResetClipEdge();
}
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
Log.i(TAG, "mUpdateRate: " + mUpdateRate);
Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
private final void init(Context context) {
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(16);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// LEGACY PAGE HANDLING!
// Create pages
mPages = new ArrayList<Bitmap>();
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.princess));
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.temp));
// Create some sample images
mForeground = mPages.get(0);
mBackground = mPages.get(1);
}
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
private Context GetContext() {
return mContext.get();
}
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
public int GetCurlSpeed()
{
return mCurlSpeed;
}
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
public int GetUpdateRate()
{
return mUpdateRate;
}
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
public int GetCurlMode()
{
return mCurlMode;
}
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
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 = specSize;
}
return result;
}
private int measureHeight(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 (beware: ascent is a negative number)
result = specSize;
}
return result;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
// Check for endings :D
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
#Deprecated
private void SwapViews() {
Bitmap temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= mPages.size()) {
foreIndex = 0;
}
int backIndex = foreIndex + 1;
if(backIndex >= mPages.size()) {
backIndex = 0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = mPages.size()-1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void setViews(int foreground, int background) {
mForeground = mPages.get(foreground);
mBackground = mPages.get(background);
}
#Override
protected void onDraw(Canvas canvas) {
mCurrentLeft = getLeft();
mCurrentTop = getTop();
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
// Restore canvas
//canvas.restore();
}
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
}
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
canvas.restore();
}
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
private void drawPageNum(Canvas canvas, int pageNum)
{
mTextPaint.setColor(Color.WHITE);
String pageNumText = "- "+pageNum+" -";
drawCentered(canvas, pageNumText,canvas.getHeight()-mTextPaint.getTextSize()-5,mTextPaint,mTextPaintShadow);
}
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setStyle(Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}
Here is the image URL for the alphabetical list view. I couldn't post it here as stackoverflow restricts me not having more reputations.
http://www.freeimagehosting.net/hwg9g
How to show this alphabetical scrollview in the left side of the screen. I have got a sample application from internet for alphabetical scrollview and i have implemented with my project :-( As a beginner i do not understand their way of coding. They have used drawRoundRect method to draw this. I regret drawRoundRect and some paint stuffs are not familiar to me..!
public class IndexScroller {
private float mIndexbarWidth;
private float mIndexbarMargin;
private float mPreviewPadding;
private float mDensity;
private float mScaledDensity;
private float mAlphaRate;
private int mState = STATE_HIDDEN;
private int mListViewWidth;
private int mListViewHeight;
private int mCurrentSection = -1;
private boolean mIsIndexing = false;
private ListView mListView = null;
private SectionIndexer mIndexer = null;
private String[] mSections = null;
private RectF mIndexbarRect;
private static final int STATE_HIDDEN = 0;
private static final int STATE_SHOWING = 1;
private static final int STATE_SHOWN = 2;
private static final int STATE_HIDING = 3;
public IndexScroller(Context context, ListView lv) {
mDensity = context.getResources().getDisplayMetrics().density;
mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
mListView = lv;
setAdapter(mListView.getAdapter());
mIndexbarWidth = 20 * mDensity;
mIndexbarMargin = 10 * mDensity;
mPreviewPadding = 5 * mDensity;
}
public void draw(Canvas canvas) {
if (mState == STATE_HIDDEN)
return;
// mAlphaRate determines the rate of opacity
Paint indexbarPaint = new Paint();
indexbarPaint.setColor(Color.BLACK);
indexbarPaint.setAlpha((int) (64 * mAlphaRate));
indexbarPaint.setAntiAlias(true);
canvas.drawRoundRect(mIndexbarRect, 5 * mDensity, 5 * mDensity,
indexbarPaint);
if (mSections != null && mSections.length > 0) {
// Preview is shown when mCurrentSection is set
if (mCurrentSection >= 0) {
Paint previewPaint = new Paint();
previewPaint.setColor(Color.BLACK);
previewPaint.setAlpha(96);
previewPaint.setAntiAlias(true);
previewPaint.setShadowLayer(3, 0, 0, Color.argb(64, 0, 0, 0));
Paint previewTextPaint = new Paint();
previewTextPaint.setColor(Color.WHITE);
previewTextPaint.setAntiAlias(true);
previewTextPaint.setTextSize(50 * mScaledDensity);
float previewTextWidth = previewTextPaint
.measureText(mSections[mCurrentSection]);
float previewSize = 2 * mPreviewPadding
+ previewTextPaint.descent()
- previewTextPaint.ascent();
RectF previewRect = new RectF(
(mListViewWidth - previewSize) / 2,
(mListViewHeight - previewSize) / 2,
(mListViewWidth - previewSize) / 2 + previewSize,
(mListViewHeight - previewSize) / 2 + previewSize);
canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity,
previewPaint);
canvas.drawText(
mSections[mCurrentSection],
previewRect.left + (previewSize - previewTextWidth) / 2
- 1,
previewRect.top + mPreviewPadding
- previewTextPaint.ascent() + 1,
previewTextPaint);
}
Paint indexPaint = new Paint();
indexPaint.setColor(Color.WHITE);
indexPaint.setAlpha((int) (255 * mAlphaRate));
indexPaint.setAntiAlias(true);
indexPaint.setTextSize(12 * mScaledDensity);
float sectionHeight = (mIndexbarRect.height() - 2 * mIndexbarMargin)
/ mSections.length;
float paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint
.ascent())) / 2;
for (int i = 0; i < mSections.length; i++) {
float paddingLeft = (mIndexbarWidth - indexPaint
.measureText(mSections[i])) / 2;
canvas.drawText(mSections[i], mIndexbarRect.left + paddingLeft,
mIndexbarRect.top + mIndexbarMargin + sectionHeight * i
+ paddingTop - indexPaint.ascent(), indexPaint);
}
}
}
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// If down event occurs inside index bar region, start indexing
if (mState != STATE_HIDDEN && contains(ev.getX(), ev.getY())) {
setState(STATE_SHOWN);
// It demonstrates that the motion event started from index bar
mIsIndexing = true;
// Determine which section the point is in, and move the list to
// that section
mCurrentSection = getSectionByPoint(ev.getY());
mListView.setSelection(mIndexer
.getPositionForSection(mCurrentSection));
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (mIsIndexing) {
// If this event moves inside index bar
if (contains(ev.getX(), ev.getY())) {
// Determine which section the point is in, and move the
// list to that section
mCurrentSection = getSectionByPoint(ev.getY());
mListView.setSelection(mIndexer
.getPositionForSection(mCurrentSection));
}
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mIsIndexing) {
mIsIndexing = false;
mCurrentSection = -1;
}
if (mState == STATE_SHOWN)
setState(STATE_HIDING);
break;
}
return false;
}
public void onSizeChanged(int w, int h, int oldw, int oldh) {
mListViewWidth = w;
mListViewHeight = h;
mIndexbarRect = new RectF(w - mIndexbarMargin - mIndexbarWidth,
mIndexbarMargin, w - mIndexbarMargin, h - mIndexbarMargin);
}
public void show() {
if (mState == STATE_HIDDEN)
setState(STATE_SHOWING);
else if (mState == STATE_HIDING)
setState(STATE_HIDING);
}
public void hide() {
if (mState == STATE_SHOWN)
setState(STATE_HIDING);
}
public void setAdapter(Adapter adapter) {
if (adapter instanceof SectionIndexer) {
mIndexer = (SectionIndexer) adapter;
mSections = (String[]) mIndexer.getSections();
}
}
private void setState(int state) {
if (state < STATE_HIDDEN || state > STATE_HIDING)
return;
mState = state;
switch (mState) {
case STATE_HIDDEN:
// Cancel any fade effect
mHandler.removeMessages(0);
break;
case STATE_SHOWING:
// Start to fade in
mAlphaRate = 0;
fade(0);
break;
case STATE_SHOWN:
// Cancel any fade effect
mHandler.removeMessages(0);
break;
case STATE_HIDING:
// Start to fade out after three seconds
mAlphaRate = 1;
fade(5000);
break;
}
}
private boolean contains(float x, float y) {
// Determine if the point is in index bar region, which includes the
// right margin of the bar
return (x >= mIndexbarRect.left && y >= mIndexbarRect.top && y <= mIndexbarRect.top
+ mIndexbarRect.height());
}
private int getSectionByPoint(float y) {
if (mSections == null || mSections.length == 0)
return 0;
if (y < mIndexbarRect.top + mIndexbarMargin)
return 0;
if (y >= mIndexbarRect.top + mIndexbarRect.height() - mIndexbarMargin)
return mSections.length - 1;
return (int) ((y - mIndexbarRect.top - mIndexbarMargin) / ((mIndexbarRect
.height() - 2 * mIndexbarMargin) / mSections.length));
}
private void fade(long delay) {
mHandler.removeMessages(0);
mHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + delay);
}
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (mState) {
case STATE_SHOWING:
// Fade in effect
mAlphaRate += (1 - mAlphaRate) * 0.2;
if (mAlphaRate > 0.9) {
mAlphaRate = 1;
setState(STATE_SHOWN);
}
mListView.invalidate();
fade(10);
break;
case STATE_SHOWN:
// If no action, hide automatically
setState(STATE_HIDING);
break;
case STATE_HIDING:
// Fade out effect
mAlphaRate -= mAlphaRate * 0.2;
if (mAlphaRate < 0.1) {
mAlphaRate = 0;
setState(STATE_HIDDEN);
}
mListView.invalidate();
fade(10);
break;
}
}
};
It would be really nice if you help me to show this alphabetical scroll bar in the left side of the screen.
I got that this way,
public void onSizeChanged(int w, int h, int oldw, int oldh) {
mListViewWidth = w;
mListViewHeight = h;
mIndexbarRect = new RectF(mIndexbarMargin, mIndexbarMargin,
mIndexbarMargin + mIndexbarWidth, h - mIndexbarMargin);
}
This is the method to draw the rectangle in left side of the screen.
private boolean contains(float x, float y) {
return (x <= mIndexbarRect.right && y >= mIndexbarRect.top && y <= mIndexbarRect.top
+ mIndexbarRect.height());
}
It will work smoothly if you change the function to the below. sorry for the posting this answer little late.
please check out : Indexable list view