recently i have started working on this app what it does is show a little joystick on the screen and when you press the arrow to android icon moves to where its pressed
this works fine in the emulator but as soon as i try it on my phone it crashes instantly
im guessing my program is using to memory so how can i limit this?
thanks
package net.jegard.software.zombie.main;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class zombView extends SurfaceView{
private Bitmap bmp, grass, joystick;
private SurfaceHolder holder;
Timer t = new Timer();
float x = 0, y = 0;
boolean forward, left, down, right;
public zombView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(final SurfaceHolder holder) {
t.scheduleAtFixedRate(new TimerTask(){
public void run(){
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
onTouchEvent(null);
}
},200,100);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
grass = BitmapFactory.decodeResource(getResources(), R.drawable.grassland);
joystick = BitmapFactory.decodeResource(getResources(), R.drawable.joystic);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(grass, getWidth() - getWidth(), getHeight() - getHeight(), null);
canvas.drawBitmap(joystick, getWidth() - getWidth(),joystick.getHeight(), null);
canvas.drawBitmap(bmp, x, y, null);
if(right){
x = x + 10;
}
if(forward){
y = y - 10;
}if(left){
x = x - 10;
}if(down){
y = y + 10;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
float tx = event.getX();
float ty = event.getY();
if(tx > (joystick.getWidth()/3)*2 && tx < (joystick.getWidth()/3)*3 && ty > (getHeight() - joystick.getHeight()) + (joystick.getHeight()/3) && ty < (getHeight() - joystick.getHeight()) + (joystick.getHeight()/3)*2){
touch_right(tx, ty);
invalidate();
}if(tx > (joystick.getWidth()/3) && tx < (joystick.getWidth()/3)*2 && ty > (getHeight() - joystick.getHeight()) && ty < (getHeight() - joystick.getHeight()) + (joystick.getHeight()/3)){
touch_forward(tx, ty);
invalidate();
}if(tx > (joystick.getWidth() - joystick.getWidth()) && tx < (joystick.getWidth()/3) && ty > (getHeight() - joystick.getHeight()) + (joystick.getHeight()/3) && ty < (getHeight() - joystick.getHeight()) + (joystick.getHeight()/3)*2){
touch_left(tx, ty);
invalidate();
}if(tx > (joystick.getWidth()/3) && tx < (joystick.getWidth()/3)*2 && ty > ((getHeight() - joystick.getHeight()) + (joystick.getHeight()/3)*2) && ty < (getHeight() - joystick.getHeight()) + (joystick.getHeight())){
touch_down(tx, ty);
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
touch_move();
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
private void touch_right(float x2, float y2) {
right = true;
}
private void touch_left(float x2, float y2) {
left = true;
}
private void touch_down(float x2, float y2) {
down = true;
}
private void touch_forward(float x2, float y2) {
forward = true;
}
private void touch_move() {
touch_up();
}
private void touch_up() {
forward = false;
right = false;
down = false;
left = false;
}
}
It may not be a memory issue at all, try connecting your phone in debug mode and check the logs. It will give you the clear picture of the real problem.
Related
I am building an app where a user can draw lines in a custom canvas with a finger (multiple fragments have a canvas and this works) using the Path class.
I also managed to use SharedPreferences to save and load the drawn lines but when loaded the lines start from the top left (i.e (0, 0)) and the shape has changed to lines with a slight curve at the start (I say start because I found that the line ends from where the touch started).
The start points are kept in Path but from what I can see there are no endpoints kept. Is there any way I can get the endpoints?
I have previously tried passing the required variables to another ArrayList that uses another constructor with the endpoints (found with a method used for when the finger stops touching the screen) but the drawings no longer showed on the canvas unlike before.
Edit
I have changed to finding multiple points as I believe that getting the endpoint won't be enough and have altered the shown code to show my attempt with getPosTan but no drawings get shown as the elements in testing are null for some reason, so it won't go in the else.
Update
I found that pathMeasure.getLength() produces 0.0 so it isn't going into the while and therefore resulting in null elements but I don't know why it's producing 0.0 as somePath isn't null
PaintView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class PaintView extends View {
public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private static ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
public Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);
}
public ArrayList getPaths() {
return paths;
}
public ArrayList setPaths(ArrayList<FingerPath> list) {
return this.paths = list;
}
public void init(DisplayMetrics metrics) {
int height = metrics.heightPixels;
int width = metrics.widthPixels;
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
loadDrawing(mCanvas);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
public void clear() {
backgroundColor = DEFAULT_BG_COLOR;
paths.clear();
normal();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mCanvas.drawColor(backgroundColor);
for (FingerPath fp : paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y) {
mPath = new Path();
FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath, x, y);
paths.add(fp);
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {mPath.lineTo(mX, mY);}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP :
touchUp();
invalidate();
break;
}
return true;
}
private FloatPoint[] getPoint(Path somePath, float x, float y){
FloatPoint[] pointArray = new FloatPoint[20];
PathMeasure pathMeasure = new PathMeasure(somePath, false);
float length = pathMeasure.getLength();
float distance = 0f;
float speed = length / 20;
int counter = 0;
float[] aCoordinates = {x, y};
while ((distance < length) && (counter < 20)) {
pathMeasure.getPosTan(distance, aCoordinates, null);
pointArray[counter] = new FloatPoint(aCoordinates[0],
aCoordinates[1]);
counter++;
distance = distance + speed;
}
return pointArray;
}
public void loadDrawing(Canvas canvas) {
if (mCanvas != null) {
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
if (! paths.isEmpty()) {
canvas.save();
mCanvas.drawColor(backgroundColor);
for (FingerPath fp : paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
FloatPoint[] testing = getPoint(fp.path, fp.x, fp.y);
//need to figure out how to for loop testing
float sectionTestX = 0.0f;
float sectionTestY = 0.0f;
for (FloatPoint testingPoint : testing) {
if (sectionTestX == 0.0f && sectionTestY == 0.0f) {
sectionTestX = testingPoint.getX();
sectionTestY = testingPoint.getY();
continue;
} else {
fp.path.quadTo(sectionTestX, sectionTestY,
testingPoint.getX(), testingPoint.getY());
sectionTestX = testingPoint.getX();
sectionTestY = testingPoint.getY();
}
}
/*xTest = fp.x;
yTest = fp.y;*/
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
}
}
}
FloatPoint.java
public class FloatPoint {
static float x, y;
public FloatPoint(float x, float y) {
this.x = x;
this.y = y;
}
public static float getX() {
return x;
}
public static float getY() {
return y;
}
}
I'm using a code for zooming my EditText and it works 100%, but the problem is when zooming the text losses its quality like zooming an image.
I need it to zoom the font in the text like making it's size bigger (size up)
This is my code for xml:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="250dp"
android:visibility="invisible"
android:background="#null"
android:id="#+id/SResult">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="250dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="1000dp"
android:visibility="invisible"
android:id="#+id/backtxt"
android:background="#android:color/white"
/>
<com.calcupital.calcupital.ZoomView
android:id="#+id/zoomView3"
android:layout_width="fill_parent"
android:layout_height="1000dp"
>
<EditText
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/Result"
android:gravity="left"
android:padding="5dp"
android:visibility="invisible"
android:textSize="16dp"
android:textColor="#android:color/black"
android:background="#null"
android:inputType="none" />
</com.calcupital.calcupital.ZoomView>
</RelativeLayout>
</ScrollView>
and java:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
public class ZoomView extends FrameLayout {
public ZoomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public ZoomView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ZoomView(final Context context) {
super(context);
}
/**
* Zooming view listener interface.
*
* #author karooolek
*
*/
public interface ZoomViewListener {
void onZoomStarted(float zoom, float zoomx, float zoomy);
void onZooming(float zoom, float zoomx, float zoomy);
void onZoomEnded(float zoom, float zoomx, float zoomy);
}
// zooming
float zoom = 1.0f;
float maxZoom = 2.0f;
float smoothZoom = 1.0f;
float zoomX, zoomY;
float smoothZoomX, smoothZoomY;
private boolean scrolling; // NOPMD by karooolek on 29.06.11 11:45
// minimap variables
private boolean showMinimap = false;
private int miniMapColor = Color.WHITE;
private int miniMapHeight = -1;
private String miniMapCaption;
private float miniMapCaptionSize = 10.0f;
private int miniMapCaptionColor = Color.WHITE;
// touching variables
private long lastTapTime;
private float touchStartX, touchStartY;
private float touchLastX, touchLastY;
private float startd;
private boolean pinching;
private float lastd;
private float lastdx1, lastdy1;
private float lastdx2, lastdy2;
// drawing
private final Matrix m = new Matrix();
private final Paint p = new Paint();
// listener
ZoomViewListener listener;
private Bitmap ch;
public float getZoom() {
return zoom;
}
public float getMaxZoom() {
return maxZoom;
}
public void setMaxZoom(final float maxZoom) {
if (maxZoom < 1.0f) {
return;
}
this.maxZoom = maxZoom;
}
public void setMiniMapEnabled(final boolean showMiniMap) {
this.showMinimap = showMiniMap;
}
public boolean isMiniMapEnabled() {
return showMinimap;
}
public void setMiniMapHeight(final int miniMapHeight) {
if (miniMapHeight < 0) {
return;
}
this.miniMapHeight = miniMapHeight;
}
public int getMiniMapHeight() {
return miniMapHeight;
}
public void setMiniMapColor(final int color) {
miniMapColor = color;
}
public int getMiniMapColor() {
return miniMapColor;
}
public String getMiniMapCaption() {
return miniMapCaption;
}
public void setMiniMapCaption(final String miniMapCaption) {
this.miniMapCaption = miniMapCaption;
}
public float getMiniMapCaptionSize() {
return miniMapCaptionSize;
}
public void setMiniMapCaptionSize(final float size) {
miniMapCaptionSize = size;
}
public int getMiniMapCaptionColor() {
return miniMapCaptionColor;
}
public void setMiniMapCaptionColor(final int color) {
miniMapCaptionColor = color;
}
public void zoomTo(final float zoom, final float x, final float y) {
this.zoom = Math.min(zoom, maxZoom);
zoomX = x;
zoomY = y;
smoothZoomTo(this.zoom, x, y);
}
public void smoothZoomTo(final float zoom, final float x, final float y) {
smoothZoom = clamp(1.0f, zoom, maxZoom);
smoothZoomX = x;
smoothZoomY = y;
if (listener != null) {
listener.onZoomStarted(smoothZoom, x, y);
}
}
public ZoomViewListener getListener() {
return listener;
}
public void setListner(final ZoomViewListener listener) {
this.listener = listener;
}
public float getZoomFocusX() {
return zoomX * zoom;
}
public float getZoomFocusY() {
return zoomY * zoom;
}
#Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
// single touch
if (ev.getPointerCount() == 1) {
processSingleTouchEvent(ev);
}
// // double touch
if (ev.getPointerCount() == 2) {
processDoubleTouchEvent(ev);
}
// redraw
getRootView().invalidate();
invalidate();
return true;
}
private void processSingleTouchEvent(final MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
final float w = miniMapHeight * (float) getWidth() / getHeight();
final float h = miniMapHeight;
final boolean touchingMiniMap = x >= 10.0f && x <= 10.0f + w
&& y >= 10.0f && y <= 10.0f + h;
if (showMinimap && smoothZoom > 1.0f && touchingMiniMap) {
processSingleTouchOnMinimap(ev);
} else {
processSingleTouchOutsideMinimap(ev);
}
}
private void processSingleTouchOnMinimap(final MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
final float w = miniMapHeight * (float) getWidth() / getHeight();
final float h = miniMapHeight;
final float zx = (x - 10.0f) / w * getWidth();
final float zy = (y - 10.0f) / h * getHeight();
smoothZoomTo(smoothZoom, zx, zy);
}
private void processSingleTouchOutsideMinimap(final MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
float lx = x - touchStartX;
float ly = y - touchStartY;
final float l = (float) Math.hypot(lx, ly);
float dx = x - touchLastX;
float dy = y - touchLastY;
touchLastX = x;
touchLastY = y;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStartX = x;
touchStartY = y;
touchLastX = x;
touchLastY = y;
dx = 0;
dy = 0;
lx = 0;
ly = 0;
scrolling = false;
break;
case MotionEvent.ACTION_MOVE:
if (scrolling || (smoothZoom > 1.0f && l > 30.0f)) {
if (!scrolling) {
scrolling = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(ev);
}
smoothZoomX -= dx / zoom;
smoothZoomY -= dy / zoom;
return;
}
break;
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_UP:
// tap
if (l < 30.0f) {
// check double tap
if (System.currentTimeMillis() - lastTapTime < 500) {
if (smoothZoom == 1.0f) {
smoothZoomTo(maxZoom, x, y);
} else {
smoothZoomTo(1.0f, getWidth() / 2.0f,
getHeight() / 2.0f);
}
lastTapTime = 0;
ev.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(ev);
return;
}
lastTapTime = System.currentTimeMillis();
performClick();
}
break;
default:
break;
}
ev.setLocation(zoomX + (x - 0.5f * getWidth()) / zoom, zoomY
+ (y - 0.5f * getHeight()) / zoom);
ev.getX();
ev.getY();
super.dispatchTouchEvent(ev);
}
private void processDoubleTouchEvent(final MotionEvent ev) {
final float x1 = ev.getX(0);
final float dx1 = x1 - lastdx1;
lastdx1 = x1;
final float y1 = ev.getY(0);
final float dy1 = y1 - lastdy1;
lastdy1 = y1;
final float x2 = ev.getX(1);
final float dx2 = x2 - lastdx2;
lastdx2 = x2;
final float y2 = ev.getY(1);
final float dy2 = y2 - lastdy2;
lastdy2 = y2;
// pointers distance
final float d = (float) Math.hypot(x2 - x1, y2 - y1);
final float dd = d - lastd;
lastd = d;
final float ld = Math.abs(d - startd);
Math.atan2(y2 - y1, x2 - x1);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startd = d;
pinching = false;
break;
case MotionEvent.ACTION_MOVE:
if (pinching || ld > 30.0f) {
pinching = true;
final float dxk = 0.5f * (dx1 + dx2);
final float dyk = 0.5f * (dy1 + dy2);
smoothZoomTo(Math.max(1.0f, zoom * d / (d - dd)), zoomX - dxk
/ zoom, zoomY - dyk / zoom);
}
break;
case MotionEvent.ACTION_UP:
default:
pinching = false;
break;
}
ev.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(ev);
}
private float clamp(final float min, final float value, final float max) {
return Math.max(min, Math.min(value, max));
}
private float lerp(final float a, final float b, final float k) {
return a + (b - a) * k;
}
private float bias(final float a, final float b, final float k) {
return Math.abs(b - a) >= k ? a + k * Math.signum(b - a) : b;
}
#Override
protected void dispatchDraw(final Canvas canvas) {
// do zoom
zoom = lerp(bias(zoom, smoothZoom, 0.05f), smoothZoom, 0.2f);
smoothZoomX = clamp(0.5f * getWidth() / smoothZoom, smoothZoomX,
getWidth() - 0.5f * getWidth() / smoothZoom);
smoothZoomY = clamp(0.5f * getHeight() / smoothZoom, smoothZoomY,
getHeight() - 0.5f * getHeight() / smoothZoom);
zoomX = lerp(bias(zoomX, smoothZoomX, 0.1f), smoothZoomX, 0.35f);
zoomY = lerp(bias(zoomY, smoothZoomY, 0.1f), smoothZoomY, 0.35f);
if (zoom != smoothZoom && listener != null) {
listener.onZooming(zoom, zoomX, zoomY);
}
final boolean animating = Math.abs(zoom - smoothZoom) > 0.0000001f
|| Math.abs(zoomX - smoothZoomX) > 0.0000001f
|| Math.abs(zoomY - smoothZoomY) > 0.0000001f;
// nothing to draw
if (getChildCount() == 0) {
return;
}
// prepare matrix
m.setTranslate(0.5f * getWidth(), 0.5f * getHeight());
m.preScale(zoom, zoom);
m.preTranslate(
-clamp(0.5f * getWidth() / zoom, zoomX, getWidth() - 0.5f
* getWidth() / zoom),
-clamp(0.5f * getHeight() / zoom, zoomY, getHeight() - 0.5f
* getHeight() / zoom));
// get view
final View v = getChildAt(0);
m.preTranslate(v.getLeft(), v.getTop());
// get drawing cache if available
if (animating && ch == null && isAnimationCacheEnabled()) {
v.setDrawingCacheEnabled(true);
ch = v.getDrawingCache();
}
// draw using cache while animating
if (animating && isAnimationCacheEnabled() && ch != null) {
p.setColor(0xffffffff);
canvas.drawBitmap(ch, m, p);
} else { // zoomed or cache unavailable
ch = null;
canvas.save();
canvas.concat(m);
v.draw(canvas);
canvas.restore();
}
// draw minimap
if (showMinimap) {
if (miniMapHeight < 0) {
miniMapHeight = getHeight() / 4;
}
canvas.translate(10.0f, 10.0f);
p.setColor(0x80000000 | 0x00ffffff & miniMapColor);
final float w = miniMapHeight * (float) getWidth() / getHeight();
final float h = miniMapHeight;
canvas.drawRect(0.0f, 0.0f, w, h, p);
if (miniMapCaption != null && miniMapCaption.length() > 0) {
p.setTextSize(miniMapCaptionSize);
p.setColor(miniMapCaptionColor);
p.setAntiAlias(true);
canvas.drawText(miniMapCaption, 10.0f,
10.0f + miniMapCaptionSize, p);
p.setAntiAlias(false);
}
p.setColor(0x80000000 | 0x00ffffff & miniMapColor);
final float dx = w * zoomX / getWidth();
final float dy = h * zoomY / getHeight();
canvas.drawRect(dx - 0.5f * w / zoom, dy - 0.5f * h / zoom, dx
+ 0.5f * w / zoom, dy + 0.5f * h / zoom, p);
canvas.translate(-10.0f, -10.0f);
}
// redraw
// if (animating) {
getRootView().invalidate();
invalidate();
// }
}
}
and this is my java code for main activity:
final static float STEP = 200;
TextView mtxtRatio1, mtxtRatio2, mtxtRatio3, mtxtRatio4;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
float fontsize = 13;
So, how can I resolve this issue and make zooming for the text without loosing the quality?
set a custom selector as background for your EditText with only colors (noImage). It "MAY" work, i didn't tested it.tell me if it works
EDIT:2
View
<Button
android:id="#+id/bButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bookbutton_selector"
android:text="Button" />
drawables/bookbutton_selector
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="false" android:drawable="#drawable/bookbutton_normal"/>
<item android:state_pressed="true" android:drawable="#drawable/bookbutton_pressed"/>
</selector>
drawables/bookbutton_normal
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="5dp" />
<gradient
android:startColor="#color/bookmany"
android:endColor="#color/bookmany_dark"
/>
</shape>
drawables/bookbutton_pressed
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="5dp" />
<gradient
android:endColor="#333"
android:startColor="#333" />
</shape>
This is a case of button, and this is also applicable for EditText with small changes in selector.
As you can see i set the selector as the background for the Button, this will help you the button to have custom style when get Clicked and Released.
Try it out. Let me know if you need more help
For some reason when I use the same code in a previous physics test without libgdx it works fine. But with libgdx it thinks the ground is in the sky.
package com.me.randomtests;
import com.badlogic.gdx.ApplicationListener;
import...
public class Randomtest implements ApplicationListener {
ShapeRenderer SR;
int x = 100, y = 100, radius = 10;
double deltax = 0, deltay = 0, gravity = 15, energyloss = .65, dt = .2;
#Override
public void create() {
SR=new ShapeRenderer();
}
#Override
public void dispose() {
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
SR.begin(ShapeType.FilledCircle);
SR.filledCircle(x, y, radius);
SR.setColor(Color.BLUE);
SR.end();
Update();
}
public void Update(){
System.out.println(y);
if(x + deltax > Gdx.graphics.getWidth() - radius -1 ){
x = Gdx.graphics.getWidth() - radius - 1;
deltax = - deltax;
}else if(x + deltax < 0 + radius){
x = 0+radius;
deltax= - deltax;
}else{
x += deltax;
}
if(y>Gdx.graphics.getHeight() - radius - 1){
y = Gdx.graphics.getHeight() - radius - 1;
deltay *=.9;
deltay = -deltay;
}else{
//vel formuka
deltay += gravity *dt;
//pos formula
y +=deltay*dt + .5*gravity*dt*dt;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
what is my problem here? Also does anyone know why 0 is at the bottom with libgdx?
I want to make a class which captures a human signature for my Android app. I have this code so far:
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
long oldTime = 0;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// paint.setColor(Color.BLACK);
// paint.setAntiAlias(true);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas) {
Path path = new Path();
if (points.size() > 1) {
for (int i = points.size() - 2; i < points.size(); i++) {
if (i >= 0) {
Point point = points.get(i);
if (i == 0) {
Point next = points.get(i + 1);
point.dx = ((next.x - point.x) / 3);
point.dy = ((next.y - point.y) / 3);
} else if (i == points.size() - 1) {
Point prev = points.get(i - 1);
point.dx = ((point.x - prev.x) / 3);
point.dy = ((point.y - prev.y) / 3);
} else {
Point next = points.get(i + 1);
Point prev = points.get(i - 1);
point.dx = ((next.x - prev.x) / 3);
point.dy = ((next.y - prev.y) / 3);
}
}
}
}
boolean first = true;
for (int i = 0; i < points.size(); i++) {
Point point = points.get(i);
if (first) {
first = false;
path.moveTo(point.x, point.y);
} else {
Point prev = points.get(i - 1);
path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x
- point.dx, point.y - point.dy, point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_UP) {
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
return true;
}
return super.onTouchEvent(event);
}
public boolean checkTime() {
//Check if there was an input 400 ms ago
long newTime = System.currentTimeMillis();
long diffirence = newTime - oldTime;
if (oldTime == 0) {
oldTime = System.currentTimeMillis();
return true;
} else if (diffirence <= 400) {
oldTime = System.currentTimeMillis();
return true;
}
return false;
}
}
class Point {
float x, y;
float dx, dy;
#Override
public String toString() {
return x + ", " + y;
}
}
The problem is that the line will connect to the latest point when I start drawing again, even when I stop drawing for a while. This is of course not very useful for capturing human signatures, that's why I created the checkTime method. If you stop drawing for 400ms it returns false, when you start drawing again it will start a new line which is not connected to the old line. I only just don't know how I can implement my method, I tried a lot but the line keeps connecting to the latest point, maybe someone can help me.
It's probably faster to create the path in onTouch and only draw it in onDraw.
Replace onTouch with
Path path = new Path();
int prevx=0;
int prevy=0;
int prevdx=0;
int prevdy=0;
public boolean onTouch(View view, MotionEvent event)
{
int x = event.getX();
int y = event.getY();
int dx = (x-prevx)/3;
int dy = (y-prevy)/3;
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
path.moveTo(x, y);
}
if(event.getAction() == MotionEvent.ACTION_MOVE)
{
path.cubicTo(prevx + prevdx, prevy + prevdy, x - dx, y - dy, x, y);
}
prevx=x;
prevy=y;
prevdx=dx;
prevdy=dy;
invalidate();
return true;
}
onDraw will be just
public void onDraw(Canvas canvas)
{
canvas.drawPath(path, paint);
}
I used this post from Lars Vogel, but many thanks to Marc Van Daele!
This is code wich paints the View:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
}
You have to call this activity to start paiting:
import android.app.Activity;
import android.os.Bundle;
public class SingleTouchActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SingleTouchEventView(this, null));
}
}
I'm trying to implement a touch responsive image view - like the one in the Gallery application. I've managed to do that, and it works well, except that it is VERY laggy compared to the stock Gallery.
I'm looking for ways to make it smoother.
Here's what I have now:
#SuppressWarnings("unused")
public class ImageDisplayView extends ImageView {
private static final String TAG = "ImageDisplayView";
private static final int MODE_NONE = 0;
private static final int MODE_DRAG = 1;
private static final int MODE_ZOOM = 2;
// Zoom Bounds
private static final float SCALE_MIN = 0.8f;
private static final float SCALE_BOTTOM = 1.0f;
private static final float SCALE_TOP = 10.0f;
private static final float SCALE_MAX = 12.0f;
// Transformation
private Matrix mMatrix = new Matrix();
private Matrix mPreMatrix = new Matrix();
private PointF mPivot = new PointF();
private PointF mNewPivot = new PointF();
private float mDist;
// State
private boolean mInitialScaleDone = false;
private boolean mEnabled = true;
private RectF mBounds = new RectF();
private Float mScale = null;
private float mMode = MODE_NONE;
public ImageDisplayView(Context context) {
super(context);
initialScale();
}
public ImageDisplayView(Context context, AttributeSet attrs) {
super(context, attrs);
initialScale();
}
public ImageDisplayView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialScale();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
initialScale();
}
private void initialScale() {
if (!mInitialScaleDone && getDrawable() != null) {
mInitialScaleDone = true;
final Runnable r = new Runnable() {
#Override
public void run() {
// Fit to screen
float scale = calculateFitScreenScale();
mMatrix.reset();
mMatrix.postScale(scale, scale);
setImageMatrix(mMatrix);
// Center
float dx = (getWidth() - mBounds.width()) / 2, dy = (getHeight() - mBounds
.height()) / 2;
mMatrix.postTranslate(dx, dy);
setImageMatrix(mMatrix);
mScale = 1.0f;
}
};
if (getWidth() == 0) {
getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
r.run();
getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
} else {
r.run();
}
}
}
#Override
public void setImageMatrix(Matrix matrix) {
super.setImageMatrix(matrix);
mBounds.set(getDrawable().getBounds());
matrix.mapRect(mBounds);
}
#Override
public void setEnabled(boolean enabled) {
mEnabled = enabled;
if (!enabled && mMode != MODE_NONE) {
if (mMode == MODE_DRAG) {
checkLimits(null);
} else {
mPivot.set(getWidth() / 2, getHeight() / 2);
updateScale();
mPreMatrix.set(mMatrix);
checkLimits(null);
}
mMode = MODE_NONE;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float scale, dx, dy;
if (mEnabled) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (event.getPointerCount() == 1) { // Start mode: drag only.
mMode = MODE_DRAG;
mPivot.set(event.getX(), event.getY());
} else { // Start mode: zoom and drag.
mMode = MODE_ZOOM;
mDist = distance(event);
midPoint(mPivot, event);
}
mPreMatrix.set(mMatrix);
return true;
case MotionEvent.ACTION_UP:
mMode = MODE_NONE;
checkLimits(event);
break;
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerCount() == 2) {
mMode = MODE_DRAG;
mPivot.set(event.getX(), event.getY());
updateScale();
mPreMatrix.set(mMatrix);
}
return true;
case MotionEvent.ACTION_MOVE:
mMatrix.set(mPreMatrix);
if (mMode == MODE_DRAG) {
dx = event.getX() - mPivot.x;
dy = event.getY() - mPivot.y;
mMatrix.postTranslate(dx, dy);
} else if (mMode == MODE_ZOOM) {
scale = distance(event) / mDist;
midPoint(mNewPivot, event);
dx = mNewPivot.x - mPivot.x;
dy = mNewPivot.y - mPivot.y;
mMatrix.postTranslate(dx, dy);
float postScale = mScale * scale;
if (postScale < SCALE_MIN) {
scale = SCALE_MIN / mScale;
} else if (postScale > SCALE_MAX) {
scale = SCALE_MAX / mScale;
}
mMatrix.postScale(scale, scale, mNewPivot.x, mNewPivot.y);
}
setImageMatrix(mMatrix);
return true;
}
}
return super.onTouchEvent(event);
}
private void updateScale() {
mScale = (mBounds.width() / getDrawable().getIntrinsicWidth())
/ calculateFitScreenScale();
}
#IntendedCaller("onTouchEvent(MotionEvent)")
private void checkLimits(MotionEvent event) {
float scale, dx, dy;
if (mScale < SCALE_BOTTOM) {
scale = SCALE_BOTTOM;
} else if (mScale > SCALE_TOP) {
scale = SCALE_TOP;
} else {
scale = mScale;
}
RectF scaleBounds = new RectF(mBounds); // Use the scale of the image
// to determine drag
// threshold.
scaleBounds.offset(getWidth() / 2 - scaleBounds.centerX(), getHeight()
/ 2 - scaleBounds.centerY());
dx = Math.min(0.0f, Math.max(0.0f, scaleBounds.left) - mBounds.left)
+ Math.max(0.0f, Math.min(getWidth(), scaleBounds.right)
- mBounds.right);
dy = Math.min(0.0f, Math.max(0.0f, scaleBounds.top) - mBounds.top)
+ Math.max(0.0f, Math.min(getHeight(), scaleBounds.bottom)
- mBounds.bottom);
animateTransformation(event, 500, null, scale, dx, dy);
}
public void animateTransformation(MotionEvent event, long duration,
final Runnable callback, final float targetScale, final float dx,
final float dy) {
mPreMatrix.set(mMatrix);
final float scale = targetScale / mScale;
final float px, py;
if (event != null) {
PointF pivot = new PointF();
midPoint(pivot, event);
px = scale > 1.0f ? mBounds.centerX() : dx > 0 ? mBounds.right
: dx < 0 ? mBounds.left : pivot.x;
py = scale > 1.0f ? mBounds.centerY() : dy > 0 ? mBounds.bottom
: dy < 0 ? mBounds.top : pivot.y;
} else {
px = mBounds.centerX();
py = mBounds.centerY();
}
Utils.animate(this, new Animator() {
#Override
public void onAnimationEnd() {
updateScale();
if (callback != null) {
callback.run();
}
}
#Override
public void makeStep(float percent) {
mMatrix.set(mPreMatrix);
float s = 1.0f + percent * (scale - 1.0f);
float tempx = dx * percent, tempy = dy * percent;
mMatrix.postTranslate(tempx, tempy);
mMatrix.postScale(s, s, px + tempx, py + tempy);
setImageMatrix(mMatrix);
}
}, duration);
}
public RectF getBounds() {
return mBounds;
}
public float getScale() {
return mScale;
}
public void scale(float scale, float px, float py) {
mMatrix.set(getImageMatrix());
mMatrix.postScale(scale, scale, px, py);
setImageMatrix(mMatrix);
mScale = scale;
}
public void translate(float dx, float dy) {
mMatrix.set(getImageMatrix());
mMatrix.postTranslate(dx, dy);
setImageMatrix(mMatrix);
}
public void resetAndCenter() {
mMatrix.set(getImageMatrix());
mMatrix.postScale(1 / mScale, 1 / mScale, mBounds.centerX(),
mBounds.centerY());
setImageMatrix(mMatrix);
// Center
float dx = (getWidth() - mBounds.width()) / 2, dy = (getHeight() - mBounds
.height()) / 2;
mMatrix.postTranslate(dx, dy);
setImageMatrix(mMatrix);
updateScale();
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mInitialScaleDone = false;
initialScale();
}
private float distance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void midPoint(PointF p, MotionEvent event) {
if (event.getPointerCount() == 1) {
p.set(event.getX(), event.getY());
} else {
p.set((event.getX(1) + event.getX(0)) / 2,
(event.getY(1) + event.getY(0)) / 2);
}
}
private float calculateFitScreenScale() {
RectF r = new RectF(getDrawable().getBounds());
float w = getWidth(), h = getHeight();
if (r.width() > r.height()) {
return w / r.width();
} else if (r.width() == r.height()) {
if (w < h) {
return w / r.width();
} else {
return h / r.height();
}
} else {
return h / r.height();
}
}
}
What can I do in order to make this less laggy? Any help much appreciated.
Have you tried it on an actual device? The emulator in notoriously slow.
Here's something that might help:
Check out the Batching section at the Android Dev Resource page:
http://developer.android.com/reference/android/view/MotionEvent.html
I've noticed that how a device batches together historical points in a continuous motion can differ considerably. This may also differ considerably between devices.
In your code, you only use getX and getY, which takes the most recent event, ignoring all the historical points.
If your device happens to be batching large amounts of historical events together, using only the most recent ones (via getX and getY) might cause lag.
The link suggests how one might consume all the historical points.
You could implement a solution that checks whether too many historical points have been batched together (event.getHistorySize() > x). If the number of historical points are above a threshold of your choosing, make intermediate frame updates based on, say, historySize / 2. Something like that.
Please review this question here
How can I get zoom functionality for images?
theres answer by Mike Ortiz down, implementing Mutli-Touch ImageView