Bitmap onClick

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Bitmap onClick

Postby mpathare » Sat Apr 18, 2009 6:49 pm

I have a custom view in which I override the onDraw method like so

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.     protected void onDraw(Canvas canvas) {
  3.  
  4.         canvas.drawBitmap(mD.getBackImage(), 0, 0, null);
  5.  
  6.     }
  7.  
  8.  
Parsed in 0.030 seconds, using GeSHi 1.0.8.4


Is there a way I can have the drawn bitmap register clicks? I would like to show a different draw a different bitmap when the one displayed on the screen is clicked.

Thanks
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Top

Postby padde » Sat Apr 18, 2009 7:59 pm

If your custom View extends Android.View or a direct/indirect Subclass you could use
View.OnClickListener to achieve your goal.
If not you could use a ImageView as container for the bitmap in your custom View and use the
OnClickListener of the ImageView.


Greets
Padde
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby mpathare » Sat Apr 18, 2009 9:01 pm

I was trying to use a custom view, but i plan to have multiple images drawn on the canvas and dont know how to get the listener to know which bitmap has been clicked on.

I am trying now to create an ImageView container or each bitmap.

I have another question. How can I access Context.getResources() in my Activity?

Thanks.
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Postby mpathare » Sat Apr 18, 2009 9:10 pm

I just wanted to clarify what I am trying to achieve. I am trying to implement a card game. I have a Deck class in which I initialize the various cards. I create images for the cards as follows


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public Deck(Resources res){
  3.  
  4.                 //create cards for all four suites
  5.  
  6.                 Card ca = new Card(res, R.drawable.ca, "clubs", 1);
  7.  
  8. }
  9.  
  10.  
Parsed in 0.030 seconds, using GeSHi 1.0.8.4


now I want to be able to do something like this from my activity

deck = new Deck(context.getResources())

but I am getting errors.
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Postby padde » Sat Apr 18, 2009 9:47 pm

To access the Context.getResources() of your Activity in other classes just
declare a public static variable of type context and assign the value "this" to it
in the onCreate method of the concerned activity.

Example
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Test extends Activity {
  3.  
  4.     public static Context testContext;
  5.  
  6.  
  7.  
  8.     public void onCreate(Bundle icicle) {
  9.  
  10.         super.onCreate(icicle);
  11.  
  12.  
  13.  
  14.         testContext = this;
  15.  
  16.  
  17.  
  18.         setContentView(R.layout.main);
  19.  
  20.     }
  21.  
  22. }
  23.  
  24.  
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


A better policy would be a private variable and pass it to the various methods.


I would build a card class as a subclass of ImageView and so "just" extend the
ImageView with functions and values to implement the Card "logic".

Similar to this...
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Card extends ImageView {
  3.  
  4.     private byte value;  // 1,2,3.... jack, queen... ace
  5.  
  6.     private byte suite;   // spades, diamonds, clubs, hearts
  7.  
  8.  
  9.  
  10.     .....
  11.  
  12. }
  13.  
  14.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


You can use the common functions of ImageView then to access the bitmap or to assign it and
your own extendes functions to access the Card values/logic.
A deck would then be just a vector of Card objects or a own class with a vector of cards and
additional functions/values/logic... depends on your needs :)

Huummmn maybe i start a poker game projekt i always wanted to do when i finished my diploma.
Maybe as a long term tutorial that successive build a poker game that covers common aspects and
problems.

Sorry.. i wander from the subject.

Greets
Padde
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby mpathare » Sat Apr 18, 2009 10:50 pm

Hey,
Thanks for your help. making the Card class as an extension of ImageView sounds like a good idea. I will try that. I have implemented the Deck as a Stack.

I am new to Java development, so a poker tutorial for Android sounds like a great idea to me! I am not trying to do anything that fancy yet, just a simple Solitaire game...

Once i have created the cards as an extension of ImageView, do I have to create a separate listener for each card?
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Top

Postby mpathare » Sat Apr 18, 2009 11:37 pm

This is what I have so far, but the onClick method does not seem to work as expected.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class GameView extends View implements OnClickListener{
  3.  
  4.         private Deck mD;
  5.  
  6.         private boolean mInit;
  7.  
  8.         private Stack<Card> mPile1, mPile2, mPile3, mPile4, mPile5, mPile6, mPile7, mOpenPile;
  9.  
  10.         private Canvas mCanvas;
  11.  
  12.        
  13.  
  14.         public GameView(Context context) {
  15.  
  16.         super(context);
  17.  
  18.         mD = new Deck(context, context.getResources());
  19.  
  20.     }
  21.  
  22.        
  23.  
  24.     @Override
  25.  
  26.     protected void onDraw(Canvas canvas) {
  27.  
  28.         mCanvas = canvas;
  29.  
  30.         initialize();
  31.  
  32.     }
  33.  
  34.    
  35.  
  36.     protected void initialize(){
  37.  
  38.         mD.shuffle();
  39.  
  40.         mD.peek().setOnClickListener(this);
  41.  
  42.         mCanvas.drawBitmap(mD.peek().getBackImage(), 0, 0, null);
  43.  
  44.     }
  45.  
  46.    
  47.  
  48.     public void onClick(View v) {
  49.  
  50.         mCanvas.drawBitmap(mD.deal().getFrontImage(), 75, 0, null);
  51.  
  52.         invalidate();
  53.  
  54.     }
  55.  
  56.  
  57.  
  58. }
  59.  
  60.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Card extends ImageView{
  3.  
  4.         private String mSuite;
  5.  
  6.         private int mRank;
  7.  
  8.         private Bitmap mImage;
  9.  
  10.         private Bitmap mBackImage;
  11.  
  12.         private int mX;
  13.  
  14.         private int mY;
  15.  
  16.         private boolean mFaceUp;
  17.  
  18.         private Context mContext;
  19.  
  20.        
  21.  
  22.         public Card(Context context, Resources res, int image, String suite, int rank){
  23.  
  24.                 super(context);
  25.  
  26.                 //BitmapFactory.Options opts = new BitmapFactory.Options();
  27.  
  28.                //opts.inJustDecodeBounds = true;
  29.  
  30.                 Bitmap bm, fm;
  31.  
  32.                 fm = BitmapFactory.decodeResource(res, image);
  33.  
  34.                 bm = BitmapFactory.decodeResource(res, R.drawable.bb1);
  35.  
  36.                 mImage = Bitmap.createScaledBitmap(fm,49, 70, true);
  37.  
  38.                 mBackImage = Bitmap.createScaledBitmap(bm,49, 70, true);
  39.  
  40.                 mSuite = suite;
  41.  
  42.                 mRank = rank;
  43.  
  44.                 mX = 0;
  45.  
  46.                 mY = 0;
  47.  
  48.                 mFaceUp = false;
  49.  
  50.                 mContext = context;
  51.  
  52.         }
  53.  
  54.        
  55.  
  56.         public Card(Context context){
  57.  
  58.                 super(context);
  59.  
  60.                
  61.  
  62.         }
  63.  
  64.         public Bitmap getFrontImage(){
  65.  
  66.                 return mImage;
  67.  
  68.         }
  69.  
  70.         public Bitmap getBackImage(){
  71.  
  72.                 return mBackImage;
  73.  
  74.         }
  75.  
  76.         public String getSuite(){
  77.  
  78.                 return mSuite;
  79.  
  80.         }
  81.  
  82.         public int getRank(){
  83.  
  84.                 return mRank;
  85.  
  86.         }
  87.  
  88.         public int getX(){
  89.  
  90.                 return mX;
  91.  
  92.         }
  93.  
  94.         public int getY(){
  95.  
  96.                 return mY;
  97.  
  98.         }
  99.  
  100.         public void setX(int x){
  101.  
  102.                 mX = x;
  103.  
  104.         }
  105.  
  106.         public void setY(int y){
  107.  
  108.                 mY = y;
  109.  
  110.         }
  111.  
  112. }//end class Card
  113.  
  114.  
Parsed in 0.040 seconds, using GeSHi 1.0.8.4


When I click on the deck I want the popped card to be displayed face up next to it. What am I missing? I have not included the Deck class and the main Activity code, let me know if you want to see it.

Thanks.
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Postby padde » Sun Apr 19, 2009 1:10 am

Well if you want to pop the upper card out of the deck
by clicking the deck (and not the card) you must implement
the clicklistener on the deck.
I would therefore also extend the deck class from ImageView
an set the bitmap of the deck to your grafik for the flipside
of the cards. The OnClickListener of the Deck checks which
card in your card stack is on top and then does what ever
you need.

Example
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class deck extends ImageView implements OnClickListener {
  3.  
  4.     private Stack cards;
  5.  
  6.     ...
  7.  
  8.  
  9.  
  10.     public void onClick(View v) {
  11.  
  12.         Card topcard = cards.peek();
  13.  
  14.         topcard.doSomeStuff();
  15.  
  16.     }
  17.  
  18.  
  19.  
  20.     ...
  21.  
  22. }
  23.  
  24.  
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


Greets
Padde
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby mpathare » Sun Apr 19, 2009 1:46 am

Hey Padde,
I am a little confused about what you said. Also, to clarify, when i said that I want clicks to register when I click the deck. I did not mean the Deck object specifically. I just want the clicks to register when I click the picture of the deck on the screen and this image is stored by every card object in the deck.

I have a Card class, Deck class and a GameView class (the GameView class is where the drawing on the canvas happens)

I have implemented Card as a subclass of ImageView. should I change it as follows

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. class Card extends ImageView implements onClickListener{
  3.  
  4.  
  5.  
  6. public Card(){//constructor
  7.  
  8. this.setOnClickListener(this);
  9.  
  10. }
  11.  
  12.  
  13.  
  14.     public void onClick(View v) {
  15.  
  16.  
  17.  
  18.     }
  19.  
  20. }
  21.  
  22.  
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


If I do this, then how do I pass information from the onClick method, to the onDraw method in GameView (this is where all the drawing happens).

Also, is it enough that the ImageView is just a wrapper around a card, or do I have to actually display the ImageView on the screen for the listener to function correctly? Currently I am only displaying the cards bitmap image....not the ImageView...
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Postby padde » Sun Apr 19, 2009 2:17 am

You have to implement the OnClickListener on the view your are actually clicking on.
Which view this at the end is depends on how you want to design your game.
You could implement a touchlistener on your gameview and check if the coordinates
of the event matches your deck position.. or you could form a deck just visually and
draw all cards on top of each other and implement a onclicklistener in the card class.
Or you could implement a onclicklistener in a deck class and do stuff from there.. like
change coordinates of a the top card and call the draw method on the game view which
draws all cards or something like that.
There are so many methods to achieve what you want.. each one have their pros and cons.

If you end up in a situation where you want to call draw UI stuff from a different class or thread just
use message/handler system of android.

And yes... you have to display the cards itself not just the bitmaps.

I will hack some stuff together to show you how i would do it and for me to check
if i dont overlook some hurdles.

Greets
Padde
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby mpathare » Sun Apr 19, 2009 3:19 pm

Hey Padde,
Thanks for all your help. I would love to see your implementation of this.
for now, I have decided to implement the listener in my gameview class. Based on the x and y coordinates of the event (I am using onTouch Listener) I do different stuff...

It seems to be working :)
mpathare
Developer
Developer
 
Posts: 26
Joined: Sat Apr 11, 2009 10:43 pm

Postby padde » Sun Apr 19, 2009 3:49 pm

Well i solved it in a different way but ontouchlistener is better because you could
drag and drop the cards with your finger or other cool stuff :)


So here is the stuff i hacked together.. not a complete game just
to show what i would do to manage a deck and cards and invoke
functions on them by onclick event and so on.

CardGameSample.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.CardGame.sample;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.widget.AbsoluteLayout;
  6.  
  7. public class CardGameSample extends Activity {
  8.     public static AbsoluteLayout layout;
  9.  
  10.     public void onCreate(Bundle savedInstanceState) {
  11.         super.onCreate(savedInstanceState);
  12.         layout = new AbsoluteLayout(this);
  13.         layout.setLayoutParams(new AbsoluteLayout.LayoutParams(
  14.             AbsoluteLayout.LayoutParams.FILL_PARENT,
  15.             AbsoluteLayout.LayoutParams.FILL_PARENT, 0, 0)
  16.         );
  17.         setContentView(layout);
  18.         Deck myDeck = CardUtils.generateDeck(layout.getContext());
  19.         myDeck.shuffle();
  20.         myDeck.setLayoutParams(new AbsoluteLayout.LayoutParams(
  21.             AbsoluteLayout.LayoutParams.WRAP_CONTENT,
  22.             AbsoluteLayout.LayoutParams.WRAP_CONTENT, 10, 10)
  23.         );
  24.         layout.addView(myDeck);
  25.     }
  26. }
  27.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


This class holds my version of your GameView.. in my case a simple AbsoluteLayout
where i add the different cards and stuff.


CardUtils.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.CardGame.sample;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.graphics.RectF;
  9.  
  10. public class CardUtils {
  11.     public final static int CardWidth = 50;
  12.     public final static int CardHeight = 80;
  13.    
  14.     public final static int spades = 9824;
  15.     public final static int hearts = 9829;
  16.     public final static int diamonds = 9670;
  17.     public final static int clubs = 9827;
  18.    
  19.     public final static Bitmap BackSide = generateBack();
  20.    
  21.    
  22.     public static Deck generateDeck(Context mContext) {
  23.         Card c;
  24.         Deck d = new Deck(mContext, generateBack());
  25.        
  26.         int[] suits = { spades, hearts, diamonds, clubs };
  27.         String[] values = { "2", "3", "4", "5", "6", "7",
  28.                             "8", "9", "10", "J", "Q", "K", "A" };
  29.        
  30.         for(int x=0; x < suits.length; x++) {
  31.             for(int y=0; y < values.length; y++) {
  32.                 c = new Card(mContext, 20, 20, values[y], suits[x],
  33.                              generateFace(values[y], suits[x]));
  34.                 d.pushCard(c);
  35.             }
  36.         }
  37.         return d;
  38.     }
  39.    
  40.     private static Bitmap generateBack() {
  41.         Bitmap back = Bitmap.createBitmap(CardWidth, CardHeight,
  42.                                           Bitmap.Config.ARGB_8888);
  43.         Canvas can = new Canvas(back);
  44.         Paint pnt = new Paint();
  45.         pnt.setColor(Color.GRAY);
  46.         pnt.setStyle(Paint.Style.FILL);
  47.         can.drawRoundRect(new RectF(0,0,CardWidth,CardHeight), 5, 5, pnt);
  48.         return back;
  49.     }
  50.    
  51.     private static Bitmap generateFace(String value, int suite) {
  52.         Bitmap face = Bitmap.createBitmap(CardWidth, CardHeight,
  53.                                           Bitmap.Config.ARGB_8888);
  54.         Canvas can = new Canvas(face);
  55.         Paint pnt = new Paint();
  56.         pnt.setStyle(Paint.Style.FILL);
  57.         pnt.setColor(Color.WHITE);
  58.         can.drawRoundRect(new RectF(0,0,CardWidth,CardHeight), 5, 5, pnt);
  59.         pnt.setTextSize(15);
  60.         if(suite == diamonds || suite == hearts)
  61.             pnt.setColor(Color.RED);
  62.         else
  63.             pnt.setColor(Color.BLACK);
  64.         can.drawText(value, (CardWidth/2)-7, (CardHeight/2)-7, pnt);
  65.         can.drawText(String.valueOf((char)suite),(CardWidth/2)-10,(CardHeight/2)+7,pnt);
  66.         return face;
  67.     }
  68. }
  69.  
Parsed in 0.047 seconds, using GeSHi 1.0.8.4


This Class is mainly for primitive Card graphics generation..


Card.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.CardGame.sample;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.view.View;
  6. import android.widget.AbsoluteLayout;
  7. import android.widget.ImageView;
  8.  
  9. public class Card extends ImageView implements View.OnClickListener{
  10.     private String value;
  11.     private int suit;
  12.     private AbsoluteLayout.LayoutParams position;
  13.     private boolean faceup = false;
  14.     private Bitmap face;
  15.     private Bitmap back;
  16.  
  17.     public Card(Context context, int x, int y, String value, int suit, Bitmap img) {
  18.         super(context);
  19.         this.position = new AbsoluteLayout.LayoutParams(
  20.                                 AbsoluteLayout.LayoutParams.WRAP_CONTENT,
  21.                                 AbsoluteLayout.LayoutParams.WRAP_CONTENT,x,y
  22.                         );
  23.         this.value = value;
  24.         this.suit = suit;
  25.         this.back = CardUtils.BackSide;
  26.         this.face = img;
  27.         this.setImageBitmap(back);
  28.         this.setLayoutParams(position);
  29.         this.setOnClickListener(this);
  30.     }
  31.    
  32.     public int getX() { return this.position.x; }
  33.     public int getY() { return this.position.y; }
  34.     public String getValue() { return this.value; }
  35.     public int getSuit() { return this.suit; }
  36.     public boolean isFaceUp() { return faceup; }
  37.  
  38.     public void setPosition(int x, int y) {
  39.         this.position.x = x;
  40.         this.position.y = y;
  41.         this.setLayoutParams(position);
  42.     }
  43.    
  44.     public void flip() {
  45.         faceup = !faceup;
  46.         if(faceup)
  47.             this.setImageBitmap(face);
  48.         else
  49.             this.setImageBitmap(back);
  50.     }
  51.    
  52.     public void onClick(View v) {
  53.         this.flip();
  54.     }
  55. }
  56.  
Parsed in 0.043 seconds, using GeSHi 1.0.8.4


Well.. this is my Card class.. it shows the Cards first with the back and onClick
it flips between face and back.


Deck.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.CardGame.sample;
  2.  
  3. import java.util.Random;
  4. import java.util.Stack;
  5.  
  6. import android.content.Context;
  7. import android.graphics.Bitmap;
  8. import android.view.View;
  9. import android.widget.ImageView;
  10.  
  11. public class Deck extends ImageView implements View.OnClickListener {
  12.     private Stack<Card> cards;
  13.    
  14.     public Deck(Context context, Bitmap back) {
  15.         super(context);
  16.         this.setImageBitmap(back);
  17.         this.cards = new Stack<Card>();
  18.         this.setOnClickListener(this);
  19.     }
  20.    
  21.     public void pushCard(Card c) { cards.push(c); }
  22.     public Card peekCard() { return cards.peek(); }
  23.     public Card popCard() { return cards.pop(); }
  24.     public int getDeckSize() { return cards.size(); }
  25.     public boolean isDeckEmpty() { return cards.isEmpty(); }
  26.  
  27.     public void shuffle() {
  28.         Card tmp;
  29.         int from,to;
  30.         Random rnd = new Random(System.currentTimeMillis());
  31.         for(int x=0; x <= 1000; x++) {
  32.             from = rnd.nextInt(cards.size());
  33.             to   = rnd.nextInt(cards.size());
  34.             tmp = cards.get(to);
  35.             cards.setElementAt(cards.elementAt(from), to);
  36.             cards.setElementAt(tmp, from);
  37.             rnd.setSeed(System.currentTimeMillis()/((from*to)+1));
  38.         }
  39.     }
  40.    
  41.     public void onClick(View v) {
  42.         if(!cards.isEmpty()) {
  43.             Card top = cards.pop();
  44.             top.setPosition(100, 100);
  45.             CardGameSample.layout.addView(top);
  46.         }
  47.     }
  48. }
  49.  
Parsed in 0.042 seconds, using GeSHi 1.0.8.4


And this is the class for the Deck.. onClick it moves the topmost card of
the deck to a different position.


This is all.. i hope it will lead to inspiration :lol:

Greets
Padde
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Top

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 4 guests