Android: Drag and Drop multiple images - java

I have this "Drag and Drop" thingy.
So basically we are making a prototype to let the user (kid) to drag and drop the candy to a jar.
The code below will works only for one candy (1 image), the second image will not move at all. I don't know why.
Any answer will be highly appreciated and I hope you can explain it because I am really new in this android development. Thank you.
These are the code I have been researching for a while
package com.example.mathventure;
import com.example.mathventure.R.drawable;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Rect;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AbsoluteLayout;
import android.widget.ImageView;
#SuppressLint("NewApi")
public class AddTutActivity extends Activity {
private static int candyInJar = 3;
private int candyOutJar = 2;
private int totalCandy;
//private String candyId;
private ImageView[] candies = new ImageView[11];
private ImageView[] candiesOut = new ImageView[candyOutJar];
private AbsoluteLayout tutLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_tut);
tutLayout = (AbsoluteLayout) findViewById(R.id.tutLayout);
tutLayout.setOnTouchListener(new touchListener());
candiesOut[0] = (ImageView) findViewById(R.id.candyOut1);
candiesOut[1] = (ImageView) findViewById(R.id.candyOut2);
candiesOut[0].setOnTouchListener(new touchListener());
candiesOut[1].setOnTouchListener(new touchListener());
totalCandy = candyInJar + candyOutJar;
for(int i=0;i<candies.length;i++){
candies[i] = new ImageView(this);
}
candies[0].setBackgroundResource(R.drawable.candy_jar_0);
candies[1].setBackgroundResource(R.drawable.candy_jar_1);
candies[2].setBackgroundResource(R.drawable.candy_jar_2);
candies[3].setBackgroundResource(R.drawable.candy_jar_3);
candies[4].setBackgroundResource(R.drawable.candy_jar_4);
candies[5].setBackgroundResource(R.drawable.candy_jar_5);
candies[6].setBackgroundResource(R.drawable.candy_jar_6);
candies[7].setBackgroundResource(R.drawable.candy_jar_7);
candies[8].setBackgroundResource(R.drawable.candy_jar_8);
candies[9].setBackgroundResource(R.drawable.candy_jar_9);
candies[10].setBackgroundResource(R.drawable.candy_jar_10);
candies[candyInJar] = (ImageView) findViewById(R.id.candyInJar);
}
private boolean dragging = false;
private Rect hitRect = new Rect();
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_add_tut, menu);
return true;
}
class touchListener extends Activity implements OnTouchListener{
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
boolean eventConsumed = true;
int x = (int)event.getX();
int y = (int)event.getY();
int dragging = 0;
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
if (v == candiesOut[0]) {
dragging = 0;
eventConsumed = false;
}
if (v == candiesOut[1]){
dragging = 1;
eventConsumed = false;
}
} else if (action == MotionEvent.ACTION_UP) {
if (dragging == 0) {
candies[candyInJar].getHitRect(hitRect);
if (hitRect.contains(x, y)){
candiesOut[0].setImageDrawable(null);
candies[candyInJar].setImageResource(drawable.candy_jar_4);
}
}
else if(dragging == 1){
candies[candyInJar].getHitRect(hitRect);
if (hitRect.contains(x, y)){
candiesOut[1].setImageDrawable(null);
candies[candyInJar].setImageResource(drawable.candy_jar_5);
}
}
eventConsumed = false;
} else if (action == MotionEvent.ACTION_MOVE) {
if (v != candiesOut[0] && v != candiesOut[1]) {
if (dragging != 1) {
setAbsoluteLocationCentered(candiesOut[dragging], x, y);
}
}
}
return eventConsumed;
}
private void setAbsoluteLocationCentered(View v, int x, int y) {
setAbsoluteLocation(v, x - v.getWidth() / 2, y - v.getHeight() / 2);
}
private void setAbsoluteLocation(View v, int x, int y) {
AbsoluteLayout.LayoutParams alp = (AbsoluteLayout.LayoutParams) v.getLayoutParams();
alp.x = x;
alp.y = y;
v.setLayoutParams(alp);
}
private void setSameAbsoluteLocation(View v1, View v2) {
AbsoluteLayout.LayoutParams alp2 = (AbsoluteLayout.LayoutParams) v2.getLayoutParams();
setAbsoluteLocation(v1, alp2.x, alp2.y);
}
}
}
this one is for the xml:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddTutActivity"
android:id="#+id/tutLayout">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="116dp"
android:fontFamily="123Marker"
android:text="3 candies + 2 candies = ?"
android:textColor="#android:color/black"
android:textSize="50sp" />
<TextView
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="123Marker"
android:text="Below is a sample question on addition. Now, you need to move the 2 candies you wanted to add into the candy jar."
android:textColor="#android:color/black"
android:textSize="25sp"
android:background="#FF3300"/>
<ImageView
android:id="#+id/candyInJar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="178dp"
android:layout_x="149dp"
android:layout_y="167dp"
android:src="#drawable/candy_jar_3" />
<ImageView
android:id="#+id/candyOut1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="94dp"
android:layout_x="489dp"
android:layout_y="347dp"
android:src="#drawable/candy" />
<ImageView
android:id="#+id/candyOut2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="544dp"
android:layout_y="346dp"
android:src="#drawable/candy" />
</AbsoluteLayout>

You might want to check out this library and example;
https://github.com/2dwarfs/MultiTouchControllerTutorial
It will get you going with creating an image which is draggable and pinchable and you can add as many as you like as simple as adding a Drawable.
You could use this as is, adjust it to only be draggable, or take some lessons and inspiration from it.

Related

Can I set two Content views in an activity?

I am new to learning android, and I am writing a program to show a point and its position(coordination) on the screen.
I use TextView to show the coordinates, and using CustomView to draw the point out.
Here is my xml.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/tv_pointX"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="X : "
android:textSize="24sp" />
<TextView
android:id="#+id/tv_pointY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="Y : "
android:textSize="24sp" />
</LinearLayout>
<com.example.pointnsendmsgtest3.svPaintCircle
android:id="#+id/TouchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp">
</com.example.pointnsendmsgtest3.svPaintCircle>
</LinearLayout>
</RelativeLayout>
And my main activity of the code. I am just wondering that how can I display all the views in one screen.
There is only one view can be displayed on the screen, base on the last setContentView command shows in my script to the compiler.
public class MainActivity extends Activity{
private TextView tv_pointx;
private TextView tv_pointy;
private LinearLayout panel_touch;
private svPaintCircle m_view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
m_view = new svPaintCircle(this);
m_view.setOnTouchListener(new MyListener());
setContentView(m_view);
setContentView(R.layout.activity_main);
}
public class MyListener implements View.OnTouchListener {
public boolean onTouch(View v, MotionEvent event){
testpoint(event);
return true;
}
private void testpoint(MotionEvent event){
if(!debugOn){
return;
}
//initialize mXs and mYs
ArrayList<Float> mXs = null;
ArrayList<Float> mYs = null;
if (mXs == null && mYs == null){
mXs = new ArrayList<Float>();
mYs = new ArrayList<Float>();
}
mXs.clear();
mYs.clear();
final int N = event.getPointerCount();
float x,y;
for(int i = 0; i < N; i++){
x = event.getX(event.getPointerId(i));
y = event.getY(event.getPointerId(i));
logd("x[" + i + "],y[" + i + "] = " + x + "," + y);
mXs.add(x);
mYs.add(y);
}
if(N > 0)m_view.setPoints(mXs,mYs);
}
}
private final boolean debugOn = true;
private final String TAG = "MyListener";
private int logd(String msg) {
int retVal = 0;
if (debugOn) {
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
Here is the class how to draw the point immediately.
public class svPaintCircle extends android.support.v7.widget.AppCompatImageView {
public svPaintCircle(Context context){
super(context);
}
public svPaintCircle(Context context, AttributeSet attrs) {super(context, attrs);}
public svPaintCircle(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
drawTouchPoint(canvas);
}
ArrayList<Float> mXs = null, mYs = null;
private boolean mDrawn = true;
private Paint mPointPaint = null;
private Paint mRectPaint = null;
private Paint mTextPaint = null;
public void setPoints(ArrayList<Float> mXs, ArrayList<Float> mYs){
if(debugOn) {
if(mPointPaint == null) {
mPointPaint = new Paint();
mPointPaint.setAntiAlias(false);
mPointPaint.setARGB(255,0,96,255);
mRectPaint = new Paint();
mRectPaint.setARGB(0x88,0x44,0x44,0x44); // 0x88 = 136 , 0x44 = 68
mTextPaint = new Paint();
mTextPaint.setTextSize(45);
mTextPaint.setARGB(0xff,0xff,0xff,0xff);
logd("init Paint");
}
this.mXs = mXs;
this.mYs = mYs;
mDrawn = false;
invalidate();
}
}
public void drawTouchPoint(Canvas canvas){
if(debugOn){
if(!mDrawn){
float x,y,rx,ry;
float dx = 80, dy = 80, r = 10;
for(int i = 0; i < mXs.size(); i++){
x = mXs.get(i);
y = mYs.get(i);
//draw cross
//canvas.drawLine(x, y - dy, x, y+dy, mPointPaint);
//canvas.drawLine(x - dx, y, x+dx ,y, mPointPaint);
canvas.drawCircle(x,y,r, mPointPaint);
rx = x;
ry = y - 40;
if(x + 75 > getRight())
rx = x -76;
if(ry < getTop())
ry = y + 20;
canvas.drawRect(0, 0, 320, 45, mRectPaint);
canvas.drawText("x: " + (int)x + " , y:" + (int)y, 0,35, mTextPaint);
}
mDrawn = true;
}
}
}
private final boolean debugOn = true;
private final String TAG = "PointView";
private int logd(String msg){
int retVal = 0;
if(debugOn){
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
How can I make both TextView and CustomView shows together?
no, you can't. setContentView can only be done for one layout.
To add some value to my answer, I would assume your understanding of setContentView is a bit wrong. setContentView is how you tell android which layout file to associate with this activity (as per your example). that's how layouts with different components are done, it's one single file with multiple or different views inside one file (or being referenced from this file, with methods such as include in xml).
From the documentation:
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
https://developer.android.com/reference/android/app/Activity.html#setContentView(int)

How to resize the bitmap image in this flood Fill algorithm code and custom view

I am new to programming and I am trying to implement a flood fill algorithm to colorize selected part in the image as a color book app.
I have found this link which provides full working code (but slow) for the algorithm. and also provide QueueLinearFloodFiller which is way faster.
The problem is that The custom MyView class is added to Relativelayout to show the bitmap that will be colored but the image is out of the view like this
I want to wrap it to fill the view and take its size like in wrap_content
I have tried to use this code to resize it
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
but it didn't work.
here is the full code and the XML
public class UnicornColorActivity extends AppCompatActivity {
private RelativeLayout dashBoard;
private MyView myView;
public ImageView image;
Button b_red, b_blue, b_green, b_orange, b_clear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_unicorn_color);
findViewById(R.id.dashBoard);
b_red = (Button) findViewById(R.id.b_red);
b_blue = (Button) findViewById(R.id.b_blue);
b_green = (Button) findViewById(R.id.b_green);
b_orange = (Button) findViewById(R.id.b_orange);
b_red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF0000);
}
});
b_blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF0000FF);
}
});
b_green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF00FF00);
}
});
b_orange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF9900);
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
}
public class MyView extends View {
private Paint paint;
private Path path;
public Bitmap mBitmap;
public ProgressDialog pd;
final Point p1 = new Point();
public Canvas canvas;
//Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
this.paint = new Paint();
this.paint.setAntiAlias(true);
pd = new ProgressDialog(context);
this.paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.unicorn_2).copy(Bitmap.Config.ARGB_8888, true);
//Bitmap.createScaledBitmap(mBitmap, 60, 60 , false);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
this.paint.setColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
public void changePaintColor(int color){
this.paint.setColor(color);
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage("Filling....");
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
// flood fill
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor, int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0 && image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0 && image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1 && image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < (height - 1) && image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="542dp"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/selectableItemBackground"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="#+id/dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/b_red"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="10dp" >
</RelativeLayout>
</android.support.v7.widget.CardView>
<Button
android:id="#+id/b_red"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#FF0000" />
<Button
android:id="#+id/b_green"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_red"
android:background="#00FF00" />
<Button
android:id="#+id/b_blue"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_green"
android:background="#0000FF" />
<Button
android:id="#+id/b_orange"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_blue"
android:background="#FF9900" />
<Button
android:id="#+id/button5"
android:layout_width="60dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Clear" />
Can Someone please help me to fix this

Trying to add a touch event on my bitmap, but i got wrong values? Android Studio

Im new on Stack Overflow!, I joined here for some problem that I got right now.
Im working with Android Studio where im trying to make a type of game that it requires a grid usage to start it. At this point im trying to implement the touch event on some bitmaps, those bitmaps are the tiles of my game but im kinda of confused, in My view, where I place all of the tiles i can get all of the coordinates (including height and width) of each tile, I check those values but when I apply the touch event (On Action Down) im getting the coords of my last tile of my grid. Thats strange, because when im drawing it in my canvas Im still got the actual values (the real coords) but in touch are different, im trying to figure this but no result at all.
Can someone here tell me where i go wrong?
Sorry for my english.
PS: The grid can be dragged.
MyView.java
package com.example.sammuzero.aplicamesta;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Map;
/**
* Created by lezama on 24-07-2017.
*/
public class MyView extends SurfaceView {
Bitmap piso1;
Bitmap muro;
Bitmap queso;
SurfaceHolder aguanta;
GameLoopThread loopGame;
Terreno pintaTerreno;
Sprite mouse;
boolean scroll;
float destinyX = 0;
float destinyY = 0;
float originX = 0;
float originY = 0;
float transX = 0;
float transY = 0;
float escala = 1;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
aguanta = getHolder();
loopGame = new GameLoopThread(this);
aguanta.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
loopGame.setRunning(true);
loopGame.start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
loopGame.setRunning(false);
while (retry) {
try {
loopGame.join();
retry = false;
} catch (InterruptedException e) {}
}
}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
queso = BitmapFactory.decodeResource(getResources(), R.drawable.kso);
pintaTerreno = new Terreno(0,0,new MapBit(piso1), new MapBit(muro));
}
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.scale(escala,escala);
canvas.translate((destinyX - originX), (destinyY - originY));
transX = (destinyX - originX);
transY = (destinyY - originY);
for(int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j ++){
dibujaCasilla(i,j, canvas);
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
}
}
canvas.scale(1.0f,1.0f);
//mouse.onDraw(canvas);
}
public void queTerrenoDibujo(Terreno e)
{
pintaTerreno = e;
}
public void setEscala(int escalaATransformar) {
float nuevaEscala;
nuevaEscala = (float) escalaATransformar / 100;
escala = nuevaEscala;
}
private void dibujaCasilla(int i, int j,Canvas canvas) {
// Primero revisa si hay una pared o no alli.
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
}
else {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
/*
MapBit nuevoBloque = null;
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
nuevoBloque = new MapBit((64 * i),(64 * j),muro);
nuevoBloque.onDraw(canvas);
}
else {
nuevoBloque = new MapBit((64 * i),(64 * j),piso1);
nuevoBloque.onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
*/
// Luego, asegurate de los elementos que estan en esa casilla.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//return super.onTouchEvent(event);
int action = event.getAction();
if (action==MotionEvent.ACTION_MOVE){
destinyX = event.getX();
destinyY = event.getY();
}
else if (action==MotionEvent.ACTION_DOWN) {
Log.i("Probando X,Y en 0,0", "X: " + pintaTerreno.getCasilla(0, 0).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(0, 0).getGrafico().getY());
for (int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j++) {
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
String msg = "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX() + " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY();
if (pintaTerreno.getCasilla(i, j).getGrafico().isCollition(event.getX(), event.getY())) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
}
}
originX = event.getX() - transX;
originY = event.getY() - transY;
scroll = true;
}
else if (action==MotionEvent.ACTION_UP){
transX = (destinyX - originX);
transY = (destinyY - originY);
scroll = false;
}
return true;
}
}
Terreno.java (The grid)
package com.example.sammuzero.aplicamesta;
import java.util.ArrayList;
import java.util.Random;
/**
*
* #author estudiante
*/
public class Terreno {
private ArrayList<Object> todo = new ArrayList<>();
private Casilla[][] plataforma;
private int alto;
private int ancho;
public Terreno (int alt, int anch, MapBit nada, MapBit pared)
{
int i;
int j;
this.plataforma = new Casilla[alt][anch];
this.alto = alt;
this.ancho = anch;
for(i = 0; i < this.alto; i++)
for(j = 0; j < this.ancho; j++)
this.plataforma[i][j] = new Casilla(i,j, nada);
this.inicializa(pared);
}
// Getters //
public int getAlto(){return this.alto;}
public int getAncho(){return this.ancho;}
public Casilla getCasilla(int i, int j){return this.plataforma[i][j];}
public ArrayList<Object> getTodo(){return this.todo;}
// Setters //
public void setEnCasilla(int x, int y, Object o, char r){this.plataforma[x][y].setObjeto(o,r);}
// Metodos //
public void inicializa(MapBit pared)
{
int cuantos = ((this.alto*this.ancho) * 10) / 100;
Random rand = new Random();
int llevo = 0;
int sel = 0;
for(int i = 0; i < this.alto ; i++)
for(int j = 0 ; j < this.ancho; j++)
{
sel = 1+rand.nextInt(10);
if(sel == 1 && llevo < cuantos)
{
Pared nueva = new Pared(this.plataforma[i][j]);
this.plataforma[i][j].setGrafico(pared);
todo.add(nueva);
llevo ++;
}
else if (sel == 10) {
Queso nuevo = new Queso(this.plataforma[i][j]);
todo.add(nuevo);
}
}
}
}
Casilla.java (the tile)
package com.example.sammuzero.aplicamesta;
import android.support.design.widget.Snackbar;
/**
* Created by lezama on 28-07-2017.
*/
public class Casilla {
private int posX;
private int posY;
private Object contenido;
private char representa;
private MapBit grafico;
public Casilla(int i, int j, MapBit graf)
{
this.posX = i;
this.posY = j;
this.representa = '0';
contenido = null;
this.grafico = graf;
}
public int getPosX() {return this.posX;}
public int getPosY() {return this.posY;}
public char getRepresenta() {return this.representa;}
public MapBit getGrafico() {return this.grafico;}
public void setObjeto(Object item , char rep)
{
this.contenido = item;
this.representa = rep;
}
public void setGrafico (MapBit grafico1) {this.grafico = grafico1;}
/*
public void onTouch()
{
Toast.makeText(this.getContext(), "X:"+this.posX+" Y:"+this.posY, Toast.LENGTH_SHORT).show();
} */
}
MapBit.java (where it resides my Bitmap)
package com.example.sammuzero.aplicamesta;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* TI, MapBit!
* Created by Samuzero15 on 28-07-2017.
*/
public class MapBit {
private float x;
private float y;
private int height;
private int width;
private Bitmap bmp;
public MapBit(Bitmap pmb)
{
this.bmp = pmb;
this.height = this.bmp.getHeight();
this.width = this.bmp.getWidth();
}
// Getmethis
public float getX(){return this.x;}
public float getY(){return this.y;}
public int getHeight(){return this.height;}
public int getWidth(){return this.width;}
public Bitmap getBitmap(){return this.bmp;}
public void setX(float newX){this.x = newX;}
public void setY(float newY){this.y = newY;}
public void onDraw(Canvas canvas)
{
canvas.drawBitmap(this.bmp,x,y,null);
}
public boolean isCollition(float x2, float y2) {
return x2 > this.x && x2 < this.x + this.width && y2 > this.y && y2 < this.y + this.height;
}
}
activity_main.xml (The main view for landscape)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
tools:context="com.example.sammuzero.aplicamesta.MainActivity">
<RelativeLayout
android:layout_width="304dp"
android:layout_height="439dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:weightSum="1"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<view
android:id="#+id/game"
class="com.example.sammuzero.aplicamesta.MyView"
id="#+id/view4"
layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="356dp"
android:gravity="center" />
<SeekBar
android:id="#+id/zoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center"
android:max="150"
android:min="25"
android:progress="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<Button
android:id="#+id/exit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Salir" />
<Button
android:id="#+id/gatos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Gatos" />
<Button
android:id="#+id/reinicio"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Repetir" />
<ImageButton
android:id="#+id/nextTurn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:srcCompat="#android:drawable/ic_media_play" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
The main activity in java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
MyView elJuego;
Button salida;
Button reset;
Button nextTurn;
SeekBar escal;
Bitmap piso1;
Bitmap muro;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
salida = (Button) findViewById(R.id.exit);
reset = (Button) findViewById(R.id.reinicio);
elJuego = (MyView) findViewById(R.id.game);
escal = (SeekBar) findViewById(R.id.zoom);
salida.setOnClickListener(this);
reset.setOnClickListener(this);
escal.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progressChanged = 0;
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
progressChanged = progress;
elJuego.setEscala(progressChanged);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
}
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.exit:
finish();
System.exit(0);
break;
case R.id.reinicio:
elJuego.invalidate();
Terreno nuevo = new Terreno(2,2,new MapBit(piso1) , new MapBit(muro));
elJuego.queTerrenoDibujo(nuevo);
default: break;
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}

how to dispatch touch events or rewrite onTouchEvent when use a scollview in viewpager?

I create a vertical viewpager like this:
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev);
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
and in the second fragment create a common viewpager with 4 fragments,and so far everything goes well,no conflicts.
Well, I put scrollviews into 3 of them,and this time when I try to scroll to the top fragment of my vertical viewpager it doesn't work with my first touch in scrollview(If I touch the other parts of this fragment it won't happen).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent"
android:orientation="horizontal"
android:layout_marginBottom="120dp"
android:paddingLeft="5dp"
android:paddingRight="5dp" >
<com.nangua.xiaomanjflc.widget.SmartScrollView
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_project_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:orientation="vertical"
android:paddingBottom="#dimen/page_bottom"
android:paddingTop="#dimen/page_small"
android:visibility="visible" >
<TextView
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="#dimen/page_line"
android:lineSpacingMultiplier="1.2"
android:textColor="#color/font_gray"
android:textSize="#dimen/font_hint" />
</LinearLayout>
</com.nangua.xiaomanjflc.widget.SmartScrollView>
</LinearLayout>
What I want is that when I scroll the scrollview over the top, it can be moved softly like my vertical viewpager does.Once I rewrited the onTouchEvent of my vertical viewpager,common viewpager and scrollview found that vertical MotionEvent action was catched by common viewpager and gone so that vertical viewpager catched nothing.
Now here's my bad solution that I put a callback in the scrollview when it scrolled to top ,the outside handle will noticed my vertical viewpager,and it scroll to the top fragment with calling setCurrentItem(0) method.But actually it seems so weird.
So what should I do when rewriting the onInterceptTouchEvent, onTouchEvent or some other useful methods of the conflicted 3 parts?
the scrollview's codes:
public SmartScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private ISmartScrollChangedListener mSmartScrollChangedListener;
public interface ISmartScrollChangedListener {
void onScrolledToBottom();
void onScrolledToTop();
}
public void setScanScrollChangedListener(
ISmartScrollChangedListener smartScrollChangedListener) {
mSmartScrollChangedListener = smartScrollChangedListener;
}
#Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
if (scrollY == 0) {
isScrolledToTop = clampedY;
isScrolledToBottom = false;
}
else {
isScrolledToTop = false;
isScrolledToBottom = clampedY;
}
notifyScrollChangedListeners();
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (getScrollY() == 0) {
isScrolledToTop = true;
isScrolledToBottom = false;
}
else if (getScrollY() + getHeight() - getPaddingTop()
- getPaddingBottom() == getChildAt(0).getHeight()) {
isScrolledToBottom = true;
isScrolledToTop = false;
}
else {
isScrolledToTop = false;
isScrolledToBottom = false;
}
notifyScrollChangedListeners();
}
}
private void notifyScrollChangedListeners() {
if (isScrolledToTop) {
if (mSmartScrollChangedListener != null) {
mSmartScrollChangedListener.onScrolledToTop();
}
}
else if (isScrolledToBottom) {
if (mSmartScrollChangedListener != null) {
mSmartScrollChangedListener.onScrolledToBottom();
}
}
}
public boolean isScrolledToTop() {
return isScrolledToTop;
}
public boolean isScrolledToBottom() {
return isScrolledToBottom;
}
public boolean canScroll() {
View child = getChildAt(0);
if (child != null) {
int childHeight = child.getHeight();
return getHeight() < childHeight;
}
return false;
}

How to Zoom a Text View in Scroll View?

I have seen a lots of code here which is helpful to zoom your textview but none of them work with my text because it is within scrollview. How can I get rid of this problem?
import android.app.Activity;
import android.os.Bundle;
import android.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
public class Introduce extends Activity implements OnTouchListener{
final static float STEP = 200;
TextView mtxtRatio1,mtxtRatio2,mtxtRatio3,mtxtRatio4;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
float fontsize = 13;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.introduce);
mtxtRatio1 = (TextView)findViewById(R.id.intro1);
mtxtRatio1.setTextSize(mRatio+13);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float)Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
mtxtRatio1.setTextSize(mRatio+13);
}
}
return true;
}
int getDistance(MotionEvent event) {
int dx = (int)(event.getX(0) - event.getX(1));
int dy = (int)(event.getY(0) - event.getY(1));
return (int)(Math.sqrt(dx * dx + dy * dy));
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
Following is the way for implementing Pinch Zoom in TextView with/without ScrollView
MainActivity.java
public class MainActivity extends AppCompatActivity{
final static float STEP = 200;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
textViewData = (TextView).findViewById(R.id.tvContributeData);
textViewData.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float) Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
textViewData.setTextSize(mRatio + 13);
}
}
return true;
});
int getDistance(MotionEvent event) {
int dx = (int) (event.getX(0) - event.getX(1));
int dy = (int) (event.getY(0) - event.getY(1));
return (int) (Math.sqrt(dx * dx + dy * dy));
}
}
}
Use Polidea's zoomview, it works in a scrollview and has pinch zoom and double tap to zoom, one thing thought, I ended up disabling the pinch zoom and just using the double tap
https://github.com/Polidea/android-zoom-view
Put your TextView andany other Views you are using into a LinearLayout that lives on a ZoomView which lives on the ScrollView, e.g.:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.polidea.ZoomView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/myLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</com.polidea.ZoomView>
</ScrollView>
Hopefully this will help others. This answer is from here and here.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
tv.setText(getString(R.string.hello_world));
scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
tv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getPointerCount() == 1){
//stuff for 1 pointer
}else{ //when 2 pointers are present
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
scaleGestureDetector.onTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
scaleGestureDetector.onTouchEvent(event);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return true;
}
});
}
The answer from here has the problem when text is resized even fingers are static (two fingers on the screen). What I did is add a check so that the textSize do not make any changes instantly.
private float safe;
public class simpleOnScaleGestureListener extends SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
// TODO Auto-generated method stub
float size = tv.getTextSize();
Log.d("TextSizeStart", String.valueOf(size));
//float factor = detector.getScaleFactor();
float factor = Math.max(0.5f, Math.min(detector.getScaleFactor(), 2f));
Log.d("Factor", String.valueOf(factor));
float product = size*factor;
Log.d("TextSize", String.valueOf(product));
safe = Math.abs(product - size);
if(product <= 100 && product >= 20 && safe < 3){
//tv.setText("factor= " +factor + "\n" + "product = \n" + size + " * " + factor + " \n= " + product +"\n" + getString(R.string.hello_world));
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, product);
}
size = tv.getTextSize();
Log.d("TextSizeEnd", String.valueOf(size));
return true;
}
}
You can play around with safe < 3 to your desired changes value.
I'm using this solution.
Crédits for Zoom Algorithm in this vídeo
Use a TextView without ScrollView, just use android:scrollbars="vertical"
<TextView
android:id="#+id/activity_content_text_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="fill"
android:textSize="8pt"
android:scrollbars="vertical"
/>
Java:
public class MainActivity extends Activity implements View.OnTouchListener {
private TextView textContent = null;
private final static float move = 200;
private float ratio = 1.0f;
private int baseDist;
private float baseRatio;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teste_layout);
textContent = findViewById(R.id.activity_content_text_content);
textContent.setText("Lorem ipsum dolor sit amet......");
textContent.setMovementMethod(new ScrollingMovementMethod());
textContent.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return onTouchEvent(event);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getPointerCount() == 2){
int action = event.getAction();
int mainAction = action&MotionEvent.ACTION_MASK;
if(mainAction == MotionEvent .ACTION_POINTER_DOWN){
baseDist = getDisTance(event);
baseRatio = ratio;
} else {
float scale = (getDisTance(event)-baseDist)/move;
float factor = (float)Math.pow(2, scale);
ratio = Math.min(1024.0f, Math.max(0.1f, baseRatio*factor));
textContent.setTextSize(ratio+15);
}
} else {
return false;
}
return true;
}
private int getDisTance(MotionEvent event) {
int dx = (int) (event.getX(0)-event.getX(1));
int dy = (int) (event.getY(0)-event.getY(1));
return (int) (Math.sqrt(dx*dx+dy*dy));
}
}

Categories