I want to add a viewflipper with multiple views in it (say 3 views with one image in each view). Following is my code :
In xml :
<ViewFlipper
android:id="#+id/view_flipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="6dip" >
<!-- The child Views/Layout to flip -->
<!-- Layout 1 for 1st Screen -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/help1" />
</LinearLayout>
<!-- Layout 2 for 2nd Screen -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/help2" />
</LinearLayout>
<!-- Layout 3 for 3rd Screen -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/help3" />
</LinearLayout>
</ViewFlipper>
In Java:
viewFlipper = (ViewFlipper) findViewById(R.id.view_flipper);
// Method to handle touch event like left to right swap and right to left swap
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen to swap
case MotionEvent.ACTION_DOWN:
{
lastX = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
// if left to right swipe on screen
if (lastX < currentX)
{
// If no more View/Child to flip
if (viewFlipper.getDisplayedChild() == 0)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Left and current Screen will go OUT from Right
viewFlipper.setInAnimation(this, R.anim.in_from_left);
viewFlipper.setOutAnimation(this, R.anim.out_to_right);
// Show the next Screen
viewFlipper.showNext();
}
// if right to left swipe on screen
if (lastX > currentX)
{
if (viewFlipper.getDisplayedChild() == 1)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Right and current Screen will go OUT from Left
viewFlipper.setInAnimation(this, R.anim.in_from_right);
viewFlipper.setOutAnimation(this, R.anim.out_to_left);
// Show The Previous Screen
viewFlipper.showPrevious();
}
break;
}
}
return false;
}
This is working except that the views come in the order 1 > 3 > 2 rather than 1 > 2 > 3 on swiping. As I am new to android I have just copied this code from elsewhere without understanding the code.
You are using ViewFlipper to swipe left and right between views. You should really use ViewPager for that.
That been said, you can do what you want with view flipper if you change your ACTION_UP to something like:
case MotionEvent.ACTION_UP: {
float currentX = touchevent.getX();
if (lastX > currentX) {
if (viewFlipper.getDisplayedChild() == 2)
break;
// anim stuff here...
viewFlipper.showNext();
}
if (lastX < currentX) {
if (viewFlipper.getDisplayedChild() == 0)
break;
// anim stuff here...
viewFlipper.showPrevious();
}
break;
}
Related
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.
I am trying to integrate viewflipper in activity which already have navigation drawer, but viewflipper not working, although navigation drawer is working. theme is to swipe a layout and show data. Below is my code
xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
tools:context="com.inabia.dailyayat.Activities.MainActivity">
<ViewFlipper
android:id="#+id/viewflipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="#+id/txtayat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center"
android:shadowColor="#ffffff"
android:shadowDx="3"
android:shadowDy="-3"
android:shadowRadius="1.5"
android:textColor="#ffd700"
android:textSize="40sp"
android:textStyle="bold" />
</LinearLayout>
</ViewFlipper>
</RelativeLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#d3d3d3"
android:cacheColorHint="#00000000"
android:choiceMode="singleChoice"
android:divider="#ffffff"
android:dividerHeight="1px" />
</android.support.v4.widget.DrawerLayout>
and java code
private ViewFlipper viewFlipper;
private float lastX;
viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
public boolean onTouchEvent(MotionEvent touchevent) {
switch (touchevent.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = touchevent.getX();
break;
case MotionEvent.ACTION_UP:
float currentX = touchevent.getX();
// Handling left to right screen swap.
if (lastX < currentX) {
// If there aren't any other children, just break.
if (viewFlipper.getDisplayedChild() == 1)
break;
// c.add(Calendar.DAY_OF_MONTH,-1);
// formattedDate = df.format(c.getTime());
// txt1.setText(formattedDate);
// Next screen comes in from left.
viewFlipper.setInAnimation(this, R.anim.slide_in_from_left);
// Current screen goes out from right.
viewFlipper.setOutAnimation(this, R.anim.slide_out_to_right);
// Display next screen.
viewFlipper.showNext();
}
// Handling right to left screen swap.
if (lastX > currentX) {
// If there is a child (to the left), kust break.
if (viewFlipper.getDisplayedChild() == 1)
break;
// c.add(Calendar.DAY_OF_MONTH,1);
// formattedDate = df.format(c.getTime());
// txt1.setText(formattedDate);
// Next screen comes in from right.
viewFlipper.setInAnimation(this, R.anim.slide_in_from_right);
// Current screen goes out from left.
viewFlipper.setOutAnimation(this, R.anim.slide_out_to_left);
// Display previous screen.
viewFlipper.showPrevious();
}
break;
}
return false;
}
Try to overide dispatchTouchEvent rather then onTouchEvent and use GestureDetector.SimpleOnGestureListener to detect all touch events on device screen hope it will work for you.
Code :
CustomGestureDetector.java
class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Swipe left (next)
if (e1.getX() > e2.getX()) {
viewFlipper.setInAnimation(context, R.anim.left_in);
viewFlipper.setOutAnimation(context, R.anim.left_out);
viewFlipper.showNext();
}
// Swipe right (previous)
if (e1.getX() < e2.getX()) {
viewFlipper.setInAnimation(context, R.anim.right_in);
viewFlipper.setOutAnimation(context, R.anim.right_out);
viewFlipper.showPrevious();
}
return super.onFling(e1, e2, velocityX, velocityY);
}
#Override
public boolean onDoubleTap(MotionEvent e) {
Log.d("Tap", "Double tap");
return super.onDoubleTap(e);
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
}
dispatchTouchEvent :
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mGestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
and in your onCreate method of activity call GestureDetector like this :
CustomGestureDetector customGestureDetector = new CustomGestureDetector();
mGestureDetector = new GestureDetector(this, customGestureDetector);
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
I've created a calendar which works fine, using a GridView which has an OnClickListener.
Now I wrapped the two GridViews in a ViewFlipper. The ViewFlipper has an OnTouchListener which also works fine, I can change the view by using ontouch when dragging. The problem is though that I have to drag on the EMTPY space in the Activity in order to use the ViewFlipper. When I drag on the GridView, nothing happends at all. But I can click on the GridView for OnClickListener.
xml:
<ViewFlipper android:id="#+id/details"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<GridView
android:id="#+id/weeks"
android:numColumns="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="8">
</GridView>
<GridView
android:id="#+id/calendar"
android:numColumns="7"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</GridView>
</LinearLayout>
android code:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// Get the action that was done on this touch event
switch (arg1.getAction())
{
case MotionEvent.ACTION_DOWN:
{
// store the X value when the user's finger was pressed down
downXValue = arg1.getX();
break;
}
case MotionEvent.ACTION_UP:
{
// Get the X value when the user released his/her finger
currentX = arg1.getX();
// going backwards: pushing stuff to the right
if (currentX - downXValue < -(arg0.getWidth()/3))
{
mdh.nextMonth();
calendar.add(Calendar.MONTH, 1);
currentMonth.setText(new SimpleDateFormat("MMMM yyyy").format(calendar.getTime()));
cAdapter.notifyDataSetChanged();
updateWeeks();
// Set the animation
vf.setInAnimation(arg0.getContext(), R.anim.push_left_in);
vf.setOutAnimation(arg0.getContext(), R.anim.push_left_out);
// Flip!
vf.showPrevious();
}
// going forwards: pushing stuff to the left
if (currentX - downXValue > arg0.getWidth()/3)
{
mdh.previousMonth();
calendar.add(Calendar.MONTH, -1);
currentMonth.setText(new SimpleDateFormat("MMMM yyyy").format(calendar.getTime()));
cAdapter.notifyDataSetChanged();
updateWeeks();
// Set the animation
vf.setInAnimation(arg0.getContext(), R.anim.push_right_in);
vf.setOutAnimation(arg0.getContext(), R.anim.push_right_out);
// Flip!
vf.showNext();
}
break;
}
gridview.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
return detector.onTouchEvent(event);
}
});
I had the same issue with a ViewFlipper and ScrollViews.
Try adding the onTouchListener to your GridView aswell and it should work.
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