OntouchListener drag across buttons - android

I am developing a piano app for android. I am trying to implement OnTouchListener for all the 8 buttons that I have in my activity. So, when the user drags or swipes his finger I want all the buttons to play the sound. I think the picture below explains it better.
See? When the user will place his hand on the first button and then drag till the last button, I want all the 8 buttons to play the song. But I am not able to achieve it. The below java code works only for the first button but the rest of the 7 buttons don't get pressed.
Here it is:
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(v.getID())
{
case(R.id.btn1):
//play button 1 sound
break;
case(R.id.btn2):
//play button 2 sound
break;
case(R.id.btn3):
//play button 3 sound
break;
case(R.id.btn4):
//play button 4 sound
break;
case(R.id.btn5):
//play button 1 sound
break;
case(R.id.btn6):
//play button 6 sound
break;
case(R.id.btn7):
//play button 7 sound
break;
case(R.id.btn8):
//play button 8 sound
break;
}
return true;
}
I have already seen this question and this as well but couldn't find an answer there.
Please help me out. Thank you for you time!

You should implement onTouchListner on the layout which contains the piano buttons
The idea is to get all piano buttons positions on the screen (x , y) after render them.
then get touch position by using getX() and getY() methods.
At this point you can handle it by checking if the touch x and y is between the view start and
end x and y, then play the sound of the view.
At this example i'am using soundpool and pitch to play different sounds (i know that it's not the perfect way), and i'm also working on x factor only because i'm using piano white keys only.
import android.app.Activity;
import android.media.*;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity
{
//The layout that holds the piano keys.
LinearLayout pianoKeysContainer;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pianoKeysContainer = (LinearLayout) findViewById(R.id.key_container);
pianoKeysContainer.setOnTouchListener(onYourViewTouchListener);
}
//Here we load the view positions after render it and fill the array with the positions
private List<Integer> positionsLeft_whiteKeys = new ArrayList<Integer>();
private List<Integer> positionsRight_whiteKeys = new ArrayList<Integer>();
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
for (int i = 0; i < pianoKeysContainer.getChildCount(); i++)
{
//positionsLeft_whiteKeys holds the start x of each view.
positionsLeft_whiteKeys.add(pianoKeysContainer.getChildAt(i).getLeft());
//positionsRight_whiteKeys holds the end x of each view.
positionsRight_whiteKeys.add(pianoKeysContainer.getChildAt(i).getRight());
}
}
public View.OnTouchListener onYourViewTouchListener = new View.OnTouchListener()
{
float positionX;
FrameLayout pianoKey;
FrameLayout lastPlayedKey;
ArrayList<FrameLayout> pressedKeys = new ArrayList<FrameLayout>();
#Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
positionX = motionEvent.getX();
float pitch;
//Looping on the child of the layout which contains the piano keys
for (int x = 0; x < ((LinearLayout) view).getChildCount(); x++)
{
// Calculating the pitch to get good chords
pitch = (float) Math.pow(Math.pow(2.0, 1 / 12.0), (float) x);
pianoKey = (FrameLayout) ((LinearLayout) view).getChildAt(x);
if (positionsLeft_whiteKeys.size() >= 0 && positionsRight_whiteKeys.size() >= 0)
{
if (positionX > positionsLeft_whiteKeys.get(x) && positionX < positionsRight_whiteKeys.get(x))
{
pianoKey = (FrameLayout) ((LinearLayout) view).getChildAt(x);
if (pianoKey != null)
{
pianoKey.setBackgroundResource(R.drawable.piano_key_pressed);
pressedKeys.add(pianoKey);
}
if (lastPlayedKey != pianoKey)
playKey(pitch);
lastPlayedKey = pianoKey;
break;
}
if (lastPlayedKey != null)
{
pianoKey.setBackgroundResource(R.drawable.piano_key);
lastPlayedKey.setBackgroundResource(R.drawable.piano_key);
}
}
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP)
{
lastPlayedKey = null;
for (FrameLayout pressedKey : pressedKeys)
{
pressedKey.setBackgroundResource(R.drawable.piano_key);
}
}
return false;
}
};
//This is sound play method
SoundPool sp = new SoundPool(1, AudioManager.STREAM_MUSIC, 1);
public void playKey(final float pitch)
{
//here you should store your piano sound at res/raw then load it
sp.load(this, R.raw.piano, 1);
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener()
{
#Override
public void onLoadComplete(SoundPool soundPool, int i, int i2)
{
soundPool.play(i, 0.99f, 0.99f, 1, 0, pitch);
}
});
}
}
And this is the xml file (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="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:id="#+id/key_container">
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"
/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_width="48dp"
android:background="#drawable/piano_key"/>
</LinearLayout>
</LinearLayout>
Note: the only thing you should do to complete the example is to put
you piano key image (pressed and not pressed) and put the piano sound
at res/raw

Related

App is crashing by adding ViewFlipper / Showing Null Object Refrence

I am working on View Flipper in android . while compiling it does not showing any error . but as soon as application starts in my mobile Devices , it crashes. Since i'm very beginner in Android and does not have enough knowledge.
Report bug shows Null Pointer Exception to invoke viewFlipper.getDisplayChild()
Main java file codes are
package com.example.joshiyogesh.classapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.ViewFlipper;
public class MainActivity extends Activity {
public ViewFlipper viewFlipper;
public float lastX;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewFlipper = (ViewFlipper)findViewById(R.id.view_flipper);
}
public boolean onTouchEvent(MotionEvent touchEvent){
switch (touchEvent.getAction()){
case MotionEvent.ACTION_DOWN:
{
lastX = touchEvent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchEvent.getX();
if (lastX<currentX){
if(viewFlipper.getDisplayedChild() == 0)
break;
viewFlipper.setInAnimation(this,R.anim.in_from_left);
viewFlipper.setOutAnimation(this,R.anim.out_from_right);
//show next Screen
viewFlipper.showNext();
}
if(lastX>currentX){
if(viewFlipper.getDisplayedChild()==1)
break;
viewFlipper.setInAnimation(this,R.anim.in_from_right);
viewFlipper.setOutAnimation(this,R.anim.out_from_left);
viewFlipper.showPrevious();
}
break;
}
}
return false;
}
}
ViewFlipper's file codes are
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewFlipper
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/view_flipper"
android:layout_margin="6dip">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
>
<ImageView
android:layout_width="450dp"
android:layout_height="450dp"
android:layout_marginTop="15dp"
android:id="#+id/image_view1"
android:src="#drawable/images"/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
>
<ImageView
android:layout_width="450dp"
android:layout_height="450dp"
android:layout_marginTop="15dp"
android:id="#+id/image_view2"
android:src="#drawable/large"/>
</LinearLayout>
</ViewFlipper>
</LinearLayout>
Any help would be Thankful.Thanks in advance.
update
Report Bug shown by devices
When using onTouchEvent the activity will send directly to it if no other functions invoke it first (ontouch listener onclick listener), you got two options
Option 1
Check if viewFlipper is null before using
Option 2
Use ontouchlistener in oncreate after findviewbyid to the flipper
viewFlipper.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
// Do what you want
return true;
}
return false;
}
});

Click event on EditText's drawableRight not working properly?

I need to open phone's contact book on the click of EditText's drawableRight. Click event on drawableRight is working fine But the problem is, when I click/touch on anywhere on EditText it is also execute click event and open contact list.
I take help for manage click event on drawableRight from here Please check this link.
I don't want to open contact list when I click on EditText, I only want to open it when I click drawableRight (image). So how solve this problem?
Here is my code:
EditText mobile_number;
mobile_number = (EditText)view.findViewById(R.id.mobile_number1);
mobile_number.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction()==MotionEvent.ACTION_UP){
if(event.getRawX()>=(mobile_number.getRight()-mobile_number.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width()));
{
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent,PICK_CONTACT);
return true;
}
}
return true;
}
});
Here is my layout code:
<LinearLayout
android:layout_width="fill_parent"
android:id="#+id/linearlayout_two1"
android:layout_below="#+id/linearlayout_one1"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginTop="20dp"
android:orientation="vertical"
>
<EditText
android:layout_width="300dp"
android:hint="Enter Your Mobile Number"
android:textSize="15sp"
android:id="#+id/mobile_number1"
android:paddingLeft="30dp"
android:layout_height="wrap_content"
android:drawableRight="#drawable/editbox_icon"
/>
</LinearLayout>
Instead of using getRawX(), try replacing that line with
if (event.getX() >= (mobile_number.getWidth() - mobile_number
.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
EDIT: I believe View.getRight() returns the position of the right edge of the View relative to its parent, while TouchEvent.getRawX() returns the absolute X position on the screen.
EDIT AGAIN TO DEMONSTRATE MY POINT:
MainActivity.xml
<RelativeLayout
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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.meremammal.www.edittextdrawable.MainActivity">
<!-- This layout is only here to demonstrate a situation that breaks the usage of getRawX() -->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true">
<EditText
android:id="#+id/edit_text"
android:layout_width="400dp"
android:layout_height="wrap_content"
android:text="Hello World!"
android:drawableRight="#android:drawable/ic_input_add"/>
</RelativeLayout>
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
EditText mEditText;
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mEditText = (EditText) findViewById(R.id.edit_text);
mEditText.setOnTouchListener(new View.OnTouchListener() {
private float touchX = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
int drawableLeft = mEditText.getRight() - mEditText
.getCompoundDrawables()[2].getBounds().width();
// This detects the location of touch on ACTION_DOWN, but because it is
// using getRawX() and getRight() and the EditText's parent is not at the
// left of the screen, it will respond when clicked in the middle of the
// EditText. Instead, use getX() and EditText.getWidth()
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getRawX() >= drawableLeft) {
touchX = event.getRawX();
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP && touchX >= drawableLeft) {
Toast.makeText(mContext, "Clicked Button", Toast.LENGTH_SHORT).show();
touchX = 0;
return true;
} else {
return mEditText.onTouchEvent(event);
}
}
});
}
}
You don't have access to the right image as far my knowledge, unless you create custom EditText class. I suggest to use a RelativeLayout, with one editText and one imageView, and set OnClickListener over the image view as below:
<RelativeLayout
android:id="#+id/rlSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:drawable/edit_text"
android:padding="5dip" >
<EditText
android:id="#+id/txtSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/imgSearch"
android:background="#00000000"
android:ems="10"/>
<ImageView
android:id="#+id/imgSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="#drawable/btnsearch" />
</RelativeLayout>
Make a Linear layout with horizontal orientation and add a edit-text and image-view with proper weight..
Then Give on click for each item separately.....
Just chage the last return to false. Also you have to remove the comma ; at the end of if statement.

Click ImageView on Specific Location

I have an imageView and when I need to let the user click only on a specific location (the white space) as shown in the image below, any suggestion?
here is my xml
<RelativeLayout
android:id="#+id/lockRelativeLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="5dp"
>
<ImageView
android:id="#+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/image" />
</RelativeLayout>
and here is the code
private View.OnTouchListener imageViewOnClickListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN){
//here i want if he clicked on specific location to go to another activity
Intent intent = new Intent(context, ViewerActivity.class);
context.startActivity(intent);
}
return true;
}
};
I don't know if i should use onClick or onTouchClick!!
You could implement the OnTouchListener.
anImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
//Check between +- 10px jsu tto have some are to hit
int centerX = (v.getWidth() /2);
if(event.getX() > centerX - 10)
&& event.getX() < centerX + 10)){
//Do your magic
}
}
return true;
}
});
The event contains the coordinates for the event.
Then you can compare that either to the the boundaries you set up or get the correct pixel from the image an check if it is white.
I would advise to put another transparent control in your relative layout on top of ImageView with paddings you need, and subscribe to its onClick event. This way you can be sure only proper area was clicked.
What i did is I used two images One for Show your Image and Secound is show only Some Part of that where you want to click
Please Note My Secound Image is my transparent image. So use one1 as a transparent image. And use its Click Event.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#xml/shape"
android:gravity="center" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/one1" />
</LinearLayout>
now create xml and create shape.xml file which is give to Linearlayout
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="20dip" />
<stroke
android:width="100dip"
android:color="#A0ffffff" />
i found a solution by myself: thanks all for replying:
private View.OnTouchListener imageViewOnClickListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
int x = (int) event.getX();
if (173 <= x && x <= 671) {
Intent intent = new Intent(context, NextActivity.class);
context.startActivity(intent);
}
return true;
}
};

Android StackView type of Layout with Horizontal Swipe

I am building an Android app that needs a "Card Deck" UI widget.
This is a request for an activity/layout example that can do the following:
1) Vertical Swipe Support:
List a deck of cards that can be vertically scrolled/swiped. StackView does this, but I'm open to any solution that works well (e.g., some CardUI project)
2) Horizontal Swipe Support:
For any card, there are 2 dictionary definitions:
If we do a left swipe - then we can see definition A.
If we do a right swipe, we see definition B
Horizontal swipe update does not update the entire screen layout, just the card that was swiped. So if I swipe Card2 to the right to see A2, I still have Card1 behind A2
Example:
[A1][Card1][B1]
[A2][Card2][B2]
[A3][Card3][B3]
I did see this related post here , the answers there provide some hints and reference info.. but unfortunately, I am still trying to figure it out.
You have two possible approaches: take some open source project and adapt it to your needs, or otherwise, build your card swipe as a image slider from a detailed tutorial.
For the first option, have a look in Github, where you will find several small projects that do deck of cards with features usually on vertical or horizontal scrolling. I guess you may find interesting the following projects:
CardDeck: Deck of Cards for Android
DeckPicker: A complete android anki droid project with some additional feature of Card Preview within browser screen. In Preview screen card will be shown like review mode on card browser window.
In the end if the additional changes you made looks nice, it can be worth to submit a patch to the original project.
For the second alternative, for the case you prefer to implement it from scratch, then take simple steps, growing your project into more specific/complex details customizing it at your will. A fullscreen image slider would fit the bill, which would comprise the activity for the view page:
activity_fullscreen_view.xml
<?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:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
And a Java class with a full screen viewer:
public class FullScreenImageAdapter extends PagerAdapter {
private Activity _activity;
private ArrayList<String> _imagePaths;
private LayoutInflater inflater;
// constructor
public FullScreenImageAdapter(Activity activity,
ArrayList<String> imagePaths) {
this._activity = activity;
this._imagePaths = imagePaths;
}
#Override
public int getCount() {
return this._imagePaths.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((RelativeLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imgDisplay;
Button btnClose;
inflater = (LayoutInflater) _activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View viewLayout = inflater.inflate(R.layout.layout_fullscreen_image, container,
false);
imgDisplay = (ImageView) viewLayout.findViewById(R.id.imgDisplay);
btnClose = (Button) viewLayout.findViewById(R.id.btnClose);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(_imagePaths.get(position), options);
imgDisplay.setImageBitmap(bitmap);
// close button click event
btnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
_activity.finish();
}
});
((ViewPager) container).addView(viewLayout);
return viewLayout;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((RelativeLayout) object);
}
}
Then you achieve the image sliding horizontally, such as:
And to add vertical motion, just include additional vertical layout:
main.xml
<?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" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Swipe Demo"
android:gravity="center"
android:layout_margin="10dip" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_margin="10dip"
android:id="#+id/image_place_holder"/>
</LinearLayout>
</LinearLayout>
Which will allow you to slide things vertically:
At the end of the day, what you want to have is a grid, such as vertical and horizontal scrolling together. For that you have to combine both vertical and horizontal sliding into a table layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent">
<TableLayout
android:id="#+id/amortization"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TableRow
android:background="#ffff00">
<TextView
android:text="#string/amortization_1"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_2"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_3"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_4"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_5"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_6"
android:padding="3dip"/>
<TextView
android:text="#string/amortization_7"
android:padding="3dip"/>
</TableRow>
</TableLayout>
</HorizontalScrollView>
</ScrollView>
Taking such steps and combining it, will allow you to achieve the effect you want.
Try this sample code-
public class Main extends Activity {
int position=0;
LinearLayout full;
Intent intent;
public Integer[] images= {
R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4,
R.drawable.image5, R.drawable.image6
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
full = (LinearLayout) findViewById(R.id.full);
changeImage();
ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
full.setOnTouchListener(activitySwipeDetector);
}
private void changeImage(){
full.setBackgroundResource(images[position]);
}
public class ActivitySwipeDetector implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
static final int MIN_DISTANCE = 100;
private float downX, upX;
Activity activity;
public ActivitySwipeDetector(Activity activity){
this.activity = activity;
}
public void onRightToLeftSwipe(){
Log.i(logTag, "RightToLeftSwipe!");
if(position < images.length - 1){
position++;
changeImage();
}
}
public void onLeftToRightSwipe(){
Log.i(logTag, "LeftToRightSwipe!");
if(position > 0){
position--;
changeImage();
}
}
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
float deltaX = downX - upX;
// swipe horizontal?
if(Math.abs(deltaX) > MIN_DISTANCE){
// left or right
if(deltaX < 0) { this.onLeftToRightSwipe(); return true; }
if(deltaX > 0) { this.onRightToLeftSwipe(); return true; }
}
else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
return false; // We don't consume the event
}
return true;
}
}
return false;
}
}
#Override
protected void onPause() {
super.onPause();
}
#Override
public void onResume()
{
super.onResume();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
}
Xml-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/full"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:orientation="vertical" />

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