Find the difference App layout not working - android

I want to create a find the difference in 2 images kind of app in Native Android.
I have done this using a Custom view with 2 images side by side and finding the touch positions (X, Y) of the image and it kind of works. But as soon as I try it on a different device the (X, Y) changes.
On one device the bitmap is (600 x 500) and the other it is (800 x 700). What can I do to get the aspect ratio same which is 6:5 on all devices?
Is there any alternate way to do this kind of App?
This is a part of my XML layout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<gamesforkids.coloring.games.multipleclickableex.CanvasView
android:id="#+id/signature_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/scene_2"
/>
<ImageView
android:id="#+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ring"
android:visibility="invisible" />
<ImageView
android:id="#+id/iv_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ring"
android:visibility="invisible" />
</FrameLayout>
This is my java onTouch code.
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.signature_canvas:
x0 = event.getX();
y0 = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
CanvasView.startTouch(x0, y0);
break;
case MotionEvent.ACTION_MOVE:
CanvasView.moveTouch(x0, y0);
break;
case MotionEvent.ACTION_UP:
CanvasView.upTouch();
Toast.makeText(this, "X_Value_" + x0 + "_Y_Value_" + y0, Toast.LENGTH_SHORT).show();
if (x0 > MyConstant.x0_min && x0 < MyConstant.x0_max && y0 > MyConstant.y0_min && y0 < MyConstant.y0_max)
{
iv.setX(((MyConstant.x0_max+MyConstant.x0_min)/2));
iv.setY(((MyConstant.y0_max+MyConstant.y0_min)/2));
iv.setVisibility(View.VISIBLE);
iv1.setX(((MyConstant.x0_max+MyConstant.x0_min)/2));
iv1.setY(((MyConstant.y0_max+MyConstant.y0_min)/2));
iv1.setVisibility(View.VISIBLE);
}
if (x0 > MyConstant.x0_min1 && x0 < MyConstant.x0_max1 && y0 > MyConstant.y0_min1 && y0 < MyConstant.y0_max1)
{
iv_a.setX(((MyConstant.x0_max1+MyConstant.x0_min1)/2));
iv_a.setY(((MyConstant.y0_max1+MyConstant.y0_min1)/2));
iv_a.setVisibility(View.VISIBLE);
iv_a1.setX(((MyConstant.x0_max1+MyConstant.x0_min1)/2));
iv_a1.setY(((MyConstant.y0_max1+MyConstant.y0_min1)/2));
iv_a1.setVisibility(View.VISIBLE);
}
break;
}
break;
}
return true;
}
Link of the screenshot of large device
and Link of the screenshot of normal device

You have to calculate offsets that depend on the current device.
There are two cases:
If the device height is more than (the height of image 1 + the height of image 2): you have to put your images in the center and you will have unused spaces in the top and in the bottom.
If the device width is more than (the width of images): you have to put your images in the center and you will have unused spaces in the left and in the right.

Related

How to display and click on buttons in a specified location on the screen?

I have written an app that shows 3 ImageViews in specified locations and by clicking on these buttons the user can navigate through the app.
To do that, first I used Bitmaps, it worked well for all type of the screens, but the problem was the memory overhead so I changed my method.
here is my code: I place ImageViews with specified with and height (in dp) and use the method "getArea" to determine which Image the user clicks, the problem is that the app interface is different on several phones and specially tablets (it does not recognizes the clicks)
my question: isn't it that "dp" is pixel independent? shouldn't it be the same on all devices? what is your suggestion in my case?
MainLayout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.arghavan.lenovo.autismo.main.MainActivity">
<ImageView
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="#drawable/main_page_background"
/>
<ImageView
android:id="#+id/balloon"
android:layout_width="190dp"
android:layout_height="270dp"
android:scaleType="fitXY"
android:src="#drawable/main_page_balloon"
android:layout_gravity="center"
android:visibility="invisible"
/>
<ImageView
android:id="#+id/rainbow"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleType="fitXY"
android:src="#drawable/main_page_rainbow"
android:layout_gravity="top|left"
android:visibility="invisible"
/>
<ImageView
android:id="#+id/sun"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="#drawable/main_page_sun"
android:layout_gravity="top|right"
android:visibility="invisible"
/>
<Button
android:id="#+id/sound_icon"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
</FrameLayout>
in MainActivity:
public void onTouch (View v, MotionEvent ev)
{
final int action = ev.getAction();
final int evX = (int) ev.getX();
final int evY = (int) ev.getY();
// If we cannot find the imageView, return.
ImageView imageView = (ImageView) v.findViewById (R.id.image);
if (imageView == null) return false;
switch (action) {
case MotionEvent.ACTION_DOWN :
int area = getArea(evX,evY);
if (area==1)
{
//do something
}
else if (area==2)
{
//do something
}
else if (area==3)
{
//do something
}
break;
default:
//do something
} // end switch
}
private int getArea(float x, float y)
{
float density = getResources().getDisplayMetrics().density;
float rx = x / density;
float ry = y / density;
if( 20< rx && rx<196 && 15<ry && ry< 159 )
return 1;
if( 86< rx && rx<293 && 138<ry && ry< 384 )
return 2;
if( 224< rx && rx<352 && 13<ry && ry< 141 )
return 3;
else
return 0;
}

Change width of the Activity's layout based on MotionEvent

What I am trying to do is to Override the dispatchTouchEvent(MotionEvent ev) method, get the actions, calculate the movement, and then show the bottom part based on the movements.
Here is my basic idea:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_DOWN:
mDownX = ev.getRawX();
mDownY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float deltaY = ev.getRawY() - mDownY;
Log.d(TAG, "delta y: " + deltaY);
if (deltaY < -50f) {
// show bottom part
}
if (deltaY > 50f) {
// close bottom part
}
break;
default:
break;
}
return false;
}
My question is: What should I use to change the width of this Activity's width and show the bottom part?
Thanks in advance :-)
Ok, so I love layout hacks.
For this example, I will have a top section and a bottom section, which is the section you would like to expose on motion event.
On your swipe function, set the visibility of the bottomBlock to visible, the animateLayoutChanges will make it look like it's sliding up.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0"
android:layout_weight="1"
android:orientation="vertical"
android:animateLayoutChanges="true" >
<LinearLayout
android:id="#+id/topBlock"
android:layout_width="match_parent"
android:layout_height="0"
android:layout_weight="1" >
</LinearLayout>
<LinearLayout
android:id="#+id/bottomBlock"
android:layout_width="match_parent"
android:layout_height="100dp"
android:visibility="gone" >
</LinearLayout>
</LinearLayout

Android Drag and Drop. Positioning image after dragging

When I drag the ImageView it is put not on the place where I let go the finger. It is placed just below and to the right. I do not understand what's wrong.
Tried various options for ImageView positioning result is the same
Layout
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF8989"
tools:context=".MainActivity" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.imageView1).setOnTouchListener(this);
findViewById(R.id.imageView1).getRootView().setOnDragListener(this);
}
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DROP:
float X = event.getX();
float Y = event.getY();
Log.d(LOGCAT, "X " + (int) X + "Y " + (int) Y);
View view = (View) event.getLocalState();
view.setX(X);
view.setY(Y);
view.setVisibility(View.VISIBLE);
default:
break;
}
return true;
}
LogCat
12-04 23:44:40.548: D/myLogs(32658): Width image 72 Height image 72
12-04 23:44:40.558: D/myLogs(32658): ACTION_DROP X 216Y 390
12-04 23:44:40.568: D/myLogs(32658): Real position: X 180.0Y 354.0
12-04 23:44:40.598: D/myLogs(32658): Drag ended
12-04 23:44:41.928: D/myLogs(32658): Width image 72 Height image 72
12-04 23:44:41.928: D/myLogs(32658): ACTION_DROP X 442Y 329
12-04 23:44:41.948: D/myLogs(32658): Real position: X 406.0Y 293.0
12-04 23:44:41.968: D/myLogs(32658): Drag ended
Replace
view.setX(X);
view.setY(Y);
with
view.setX(X-(view.getWidth()/2));
view.setY(Y-(view.getHeight()/2));
It's because it's placing the image's top left corner to where you realease.
To have it do what you want, basically you will need to subtract half of the image's width from X and half of it's height from Y.
So you should have something like this:
view.setX((X - (image.width / 2));
view.setY(Y - (image.width / 2));
v.setX(me.getRawX() - (v.getWidth() / 2));
v.setY(me.getRawY() - (float)(v.getHeight()* 1.5 / 2));
I found this solution as perfect answer where as dragging from the center of the object.
Just incase someone needs help with this:
I tried it and found that the problem is with the rootview, if you give your layout an id (the one you are moving the image in) and than relace
findViewById(R.id.imageView1).getRootView().setOnDragListener(this);
findViewById(R.id.imageView1).getRootView().findViewById(R.id.yourLayout).setOnDragListener(this);
That should do it.
for placing imageView in the middle try what others already said:
view.setX(X - iv.getWidth()/2);
view.setY(Y - iv.getHeight()/2) ;
This will place the imageView in the middle
Happy programming :)

Why my animation does not stop in the to-x given value?

I want to move a view on touch and when the user unholds this view, it is started an animation which moves my view to the end of its parent.
This is my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/time_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<AbsoluteLayout
android:id="#+id/slide_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:background="#0000FF" >
<View
android:id="#+id/slide_to_pause"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00FFFF" />
</AbsoluteLayout>
</RelativeLayout>
This is how I set the view to move in my onCreate:
slideView = ((View) findViewById(R.id.slide_to_pause));
slideView.setOnTouchListener(this);
This is how I move the view and starts the animation:
#Override
public boolean onTouch(View view, MotionEvent event) {
AbsoluteLayout.LayoutParams layoutParams = (AbsoluteLayout.LayoutParams) view.getLayoutParams();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mX = event.getRawX();
break;
case MotionEvent.ACTION_UP:
int endOfAnimation = findViewById(R.id.slide_layout).getWidth() - view.getWidth();
mSlideAnimation = new TranslateAnimation(0, endOfAnimation - layoutParams.x, 0, 0);
mSlideAnimation.setDuration(1000);
view.startAnimation(mSlideAnimation);
Log.d(TAG, "endOfAnimation = " + layoutParams.x + " | " + endOfAnimation);
break;
case MotionEvent.ACTION_MOVE:
layoutParams.x = (int) event.getRawX();
view.setLayoutParams(layoutParams);
break;
}
return true;
}
The problem is that when the view arrives at the end it comes back to a point in the midle of the screen, which is the point where the user unholds the view.
How can I fix this?
Thank you!
You need to use
mSlideAnimation.setFillAfter(true);
to make it not revert back to the start.
If that doesn't work you might have to follow the suggestion on Animation.setFillAfter/Before - Do they work/What are they for?
You can simulate animation manually (move views yourself, without animation framework) by using
View.offsetLeftAndRight(int offset)
View.offsetTopAndBottom(int offset)

scroll an image bigger than the screen and stop at its border on Android

I know how to display an image that is bigger than the screen. That's fairly simple and explained in details here, however, this method makes you able to scroll as far as you want, event if you have left the image and you just have black screen. I would like to know how we can make the scrolling stop when we reach the side of the picture...
Load your image into a WebView. Then you will get all the scroll behaviors you are looking for, and even the default zoom controls if you choose to turn them on...practically for free. Your only other option (to my knowledge) would be to used the 2D graphics APIs (Canvas, etc.) and create your own version of drawing tiles (like viewing a section of a map).
If your image is local, take a look at this example of reading local image data in from the SD Card. The cleaner approach to serving a local image in this case would be to create a ContentProvider and access the resource through a content:// URL in your WebView.
Example using the bundled image car.jpg in the assets directory of your project:
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<WebView
android:id="#+id/web"
android:layout_width="150dip"
android:layout_height="150dip"
/>
</LinearLayout>
src/ImageViewer.java
public class ImageViewer extends Activity {
WebView webView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)findViewById(R.id.web);
webView.loadUrl("file:///android_asset/car.jpg");
}
}
For an image bundled with your project, that's the simplest method. This does not work with images in your resources directory (like res/drawable). That path is not worth the code required to complete it.
In your Activity.onCreate():
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(...);
I was not sure which layout you exactly mean so I am posting 2 versions:
Version 1 (Buton below the image):
<?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:orientation="vertical">
<ScrollView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="1"
android:fadingEdge="none" android:scrollbars="none">
<ImageView android:id="#+id/image" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:scaleType="center" />
</ScrollView>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="OK"
android:layout_gravity="center" />
</LinearLayout>
Version 2 (Button over the image - in z axis):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ScrollView android:layout_width="fill_parent"
android:layout_height="fill_parent" android:fadingEdge="none"
android:scrollbars="none">
<ImageView android:id="#+id/image" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:scaleType="center" />
</ScrollView>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="OK"
android:layout_gravity="bottom|center_horizontal" />
</FrameLayout>
You can also try putting ScrollView inside a HorizontalScrollView.
Well I had same issue here is my solution:
Display display = getWindowManager().getDefaultDisplay();
screenSize = new Point();
display.getSize(screenSize);
Get screen size it will be required to set bottom and right boundaries
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float curX, curY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
rect = image.getDrawable().getBounds();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
image.scrollBy(getX((int) (mx - curX)), getY((int) (my - curY)));
mx = curX;
my = curY;
break;
}
return true;
}
});
and finally two methods to set new scroll coordinates
private int getX(int x){
if (image.getScrollX() + x < 0 ){ //left side
return 0;
} else if (image.getScrollX() + x >= (rect.right - screenSize.x)){ //right side
return 0;
} else {
return x;
}
}
private int getY(int y){
if (image.getScrollY() + y < 0 ){ //top side
return 0;
} else if (image.getScrollY() + y >= (rect.bottom - screenSize.y)){ //bottom side
return 0;
} else {
return y;
}
}
Works great API 16+, hope it will help

Categories

Resources