tags:

views:

4449

answers:

2

I am writing a solitaire app. I use a canvas to draw everything on the screen. Sometimes a pile of cards will get big and extend below the bottom of the screen. I would like to make the canvas scrollable so the user can access those cards.

main activity

package com.maulinpathare.solitaire;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class Solitaire extends Activity{
    /** Called when the activity is first created. */
     private Context mContext;
     private GameView mG;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        setContentView(R.layout.main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        boolean result = super.onCreateOptionsMenu(menu);
        menu.add(0, 1, 0, R.string.newGame);
        menu.add(0, 2, 0, R.string.exitGame);
        return result;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case 1:
          mG = new GameView(this);
          setContentView(mG);
            return true;
        case 2:
            finish();
            return true;
        }
        return false;
    }

}//end class

GameView Class This is where everything happens I have removed most of the game logic...

package com.maulinpathare.solitaire;

import java.util.Stack;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ScrollView;

public class GameView extends ScrollView implements OnTouchListener{
     private Deck mD;
     private boolean mInit, mDone;
     private Stack<Card> mPile1, mPile2, mPile3, mPile4, mPile5, mPile6, mPile7,
                              mOpenPile, mEndPile1, mEndPile2, mEndPile3, mEndPile4, mTemp;
     private Canvas mCanvas;
     private int mPile;
     private boolean mPickUp, mVictory;
     private Card mCard;
     private final int mSpacing = 22;
     private Paint rectPaint, wonPaint1, wonPaint2;

     public GameView(Context context) {
        super(context);
                    //initialize everything needed for the game
    }

    @Override
    protected void onDraw(Canvas canvas) {
     mCanvas = canvas;
     if(mInit){
          initialize();
          mInit = false;
     }
        //draw stuff...

    }//end onDraw

    public boolean onTouch(View v, MotionEvent event){
     int eventAction = event.getAction();
     int x = Math.round(event.getX());
     int y = Math.round(event.getY());

     switch(eventAction){
     case MotionEvent.ACTION_DOWN:
                    //check if touch has happened on one of the card piles
          break; //end case action_touch

     case MotionEvent.ACTION_MOVE:
                    //if card touched move it
          break; //end case action_move

     case MotionEvent.ACTION_UP:
                    //check if legal move has been made
          break; //end case action_up

     }//end switch(event)

     invalidate();
     return true;
    }//end onTouch
}

Where and how should I implement screen scrolling? I would like the user to be able to slide their finger across the screen in the direction they want to scroll.

A: 

See android.widget.Scroller and android.view.VelocityTracker. They will let you implement a custom scrolling view.
Also, you could just put your Canvas in a ScrollView...

Isaac Waller
Yea, someone on another forum also told me to do that. I now have added my GameView as a child to a ScrollView. The scrolling now works fine, but because the ScrollView eats all the touch events, interacting with the cards is now broken. I am trying to figure out if there is some way to have the ScrollView only accept certain events and pass the rest to its children.
Maulin
A: 

Interesting stuff, the way I understood views to work in Android is that the inner views receive all touch events and the events are only passed to the wrapper views if the onTouchEvent of the inner views return 0 (To say they haven't dealt with it) that is unless the parent view intercepts the touch events.

You need to override onInterceptTouchEvent I think;

ScrollView

You want the events that are intercepted to be passed on to child views in more situations than they are currently.

I find it's often useful to look at the source as the documentation can be patchy.

Sorry I can't be of more help, hopefully you can find your answer by playing around with an extended view.

Gav

gav