How do I implement background scrolling with a gridview? If it sounds vague, I mean like implementing a bookshelf using a gridview where the shelf image is attached to an item in the gridview.
It took me forever to figure this out, so for everybody trying to do this, here's the code from my e-book reader.
It's based on Shelves by Romain Guy so he deserves the credit for the original code.
package net.nightwhistler.pageturner.view;
import net.nightwhistler.pageturner.R;
import net.nightwhistler.pageturner.library.LibraryBook;
import net.nightwhistler.pageturner.library.QueryResult;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.GridView;
public class BookCaseView extends GridView {
private Bitmap background;
private int mShelfWidth;
private int mShelfHeight;
private QueryResult<LibraryBook> result;
private LibraryBook selectedBook;
public BookCaseView(Context context, AttributeSet attributes) {
super(context, attributes);
this.setFocusableInTouchMode(true);
this.setClickable(false);
final Bitmap shelfBackground = BitmapFactory.decodeResource(context.getResources(),
R.drawable.shelf_single);
setBackground(shelfBackground);
this.setFocusable(true);
}
public void setBackground(Bitmap background) {
this.background = background;
mShelfWidth = background.getWidth();
mShelfHeight = background.getHeight();
}
protected void onClick( int bookIndex ) {
LibraryBook book = this.result.getItemAt(bookIndex);
this.selectedBook = book;
invalidate();
}
#Override
protected void dispatchDraw(Canvas canvas) {
final int count = getChildCount();
final int top = count > 0 ? getChildAt(0).getTop() : 0;
final int shelfWidth = mShelfWidth;
final int shelfHeight = mShelfHeight;
final int width = getWidth();
final int height = getHeight();
final Bitmap background = this.background;
for (int x = 0; x < width; x += shelfWidth) {
for (int y = top; y < height; y += shelfHeight) {
canvas.drawBitmap(background, x, y, null);
}
//This draws the top pixels of the shelf above the current one
Rect source = new Rect(0, mShelfHeight - top, mShelfWidth, mShelfHeight);
Rect dest = new Rect(x, 0, x + mShelfWidth, top );
canvas.drawBitmap(background, source, dest, null);
}
super.dispatchDraw(canvas);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ( keyCode == KeyEvent.KEYCODE_BACK && this.selectedBook != null ) {
this.selectedBook = null;
invalidate();
return true;
}
return false;
}
}
What I did was to split my background image in n gridview columns and in my gridview getView method add the view background according to the position in the grid.
It worked perfectly.
If you want the code just ask.
My previous answer only adds the background but doesn't let it scroll with the items. what you wan is NightWhistler's answer :)
Sorry for misinterpreting the question.
Related
I've made a data table using a GridView and would like to apply a horizontal divider below each row as shown in the Google material design guidelines. However, I cannot find any information on its implementation. Any ideas?
Try to give background color to GridView like this
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e5e5e5"
android:horizontalSpacing="1dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="1dp" >
Give horizontalSpacing and verticalSpacing's size in dp
and give background color which you want as a divider
like Grey
Use the GridView's android:horizontalSpacing attribute.
Just Create Custom gridview like this
package net.nightwhistler.pageturner.view;
import net.nightwhistler.pageturner.R;
import net.nightwhistler.pageturner.library.LibraryBook;
import net.nightwhistler.pageturner.library.QueryResult;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.GridView;
public class BookCaseView extends GridView {
private Bitmap background;
private int mShelfWidth;
private int mShelfHeight;
private QueryResult<LibraryBook> result;
private LibraryBook selectedBook;
public BookCaseView(Context context, AttributeSet attributes) {
super(context, attributes);
this.setFocusableInTouchMode(true);
this.setClickable(false);
final Bitmap shelfBackground = BitmapFactory.decodeResource(context.getResources(),
R.drawable.shelf_single);
setBackground(shelfBackground);
this.setFocusable(true);
}
public void setBackground(Bitmap background) {
this.background = background;
mShelfWidth = background.getWidth();
mShelfHeight = background.getHeight();
}
protected void onClick( int bookIndex ) {
LibraryBook book = this.result.getItemAt(bookIndex);
this.selectedBook = book;
invalidate();
}
#Override
protected void dispatchDraw(Canvas canvas) {
final int count = getChildCount();
final int top = count > 0 ? getChildAt(0).getTop() : 0;
final int shelfWidth = mShelfWidth;
final int shelfHeight = mShelfHeight;
final int width = getWidth();
final int height = getHeight();
final Bitmap background = this.background;
for (int x = 0; x < width; x += shelfWidth) {
for (int y = top; y < height; y += shelfHeight) {
canvas.drawBitmap(background, x, y, null);
}
//This draws the top pixels of the shelf above the current one
Rect source = new Rect(0, mShelfHeight - top, mShelfWidth, mShelfHeight);
Rect dest = new Rect(x, 0, x + mShelfWidth, top );
canvas.drawBitmap(background, source, dest, null);
}
super.dispatchDraw(canvas);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ( keyCode == KeyEvent.KEYCODE_BACK && this.selectedBook != null ) {
this.selectedBook = null;
invalidate();
return true;
}
return false;
}
}
I got his answer from her
background scrolling with item in gridview
I'm currently using a BluringView XML Object as gotten from the BlurringView.java file (https://github.com/500px/500px-android-blur). It's basically just a custom view that blurs a sibling view that's beneath it. The problem I'm having is that I can't populate the BlurringView with other objects. Here's the code:
package com.fivehundredpx.android.blur;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;
import android.util.AttributeSet;
import android.view.View;
/**
* A custom view for presenting a dynamically blurred version of another view's content.
* <p/>
* Use {#link #setBlurredView(android.view.View)} to set up the reference to the view to be blurred.
* After that, call {#link #invalidate()} to trigger blurring whenever necessary.
*/
public class BlurringView extends View {
public BlurringView(Context context) {
this(context, null);
}
public BlurringView(Context context, AttributeSet attrs) {
super(context, attrs);
final Resources res = getResources();
final int defaultBlurRadius = res.getInteger(R.integer.default_blur_radius);
final int defaultDownsampleFactor = res.getInteger(R.integer.default_downsample_factor);
final int defaultOverlayColor = res.getColor(R.color.default_overlay_color);
initializeRenderScript(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PxBlurringView);
setBlurRadius(a.getInt(R.styleable.PxBlurringView_blurRadius, defaultBlurRadius));
setDownsampleFactor(a.getInt(R.styleable.PxBlurringView_downsampleFactor,
defaultDownsampleFactor));
setOverlayColor(a.getColor(R.styleable.PxBlurringView_overlayColor, defaultOverlayColor));
a.recycle();
}
public void setBlurredView(View blurredView) {
mBlurredView = blurredView;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBlurredView != null) {
if (prepare()) {
// If the background of the blurred view is a color drawable, we use it to clear
// the blurring canvas, which ensures that edges of the child views are blurred
// as well; otherwise we clear the blurring canvas with a transparent color.
if (mBlurredView.getBackground() != null && mBlurredView.getBackground() instanceof ColorDrawable){
mBitmapToBlur.eraseColor(((ColorDrawable) mBlurredView.getBackground()).getColor());
}else {
mBitmapToBlur.eraseColor(Color.TRANSPARENT);
}
mBlurredView.draw(mBlurringCanvas);
blur();
canvas.save();
canvas.translate(mBlurredView.getX() - getX(), mBlurredView.getY() - getY());
canvas.scale(mDownsampleFactor, mDownsampleFactor);
canvas.drawBitmap(mBlurredBitmap, 0, 0, null);
canvas.restore();
}
canvas.drawColor(mOverlayColor);
}
}
public void setBlurRadius(int radius) {
mBlurScript.setRadius(radius);
}
public void setDownsampleFactor(int factor) {
if (factor <= 0) {
throw new IllegalArgumentException("Downsample factor must be greater than 0.");
}
if (mDownsampleFactor != factor) {
mDownsampleFactor = factor;
mDownsampleFactorChanged = true;
}
}
public void setOverlayColor(int color) {
mOverlayColor = color;
}
private void initializeRenderScript(Context context) {
mRenderScript = RenderScript.create(context);
mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript));
}
protected boolean prepare() {
final int width = mBlurredView.getWidth();
final int height = mBlurredView.getHeight();
if (mBlurringCanvas == null || mDownsampleFactorChanged
|| mBlurredViewWidth != width || mBlurredViewHeight != height) {
mDownsampleFactorChanged = false;
mBlurredViewWidth = width;
mBlurredViewHeight = height;
int scaledWidth = width / mDownsampleFactor;
int scaledHeight = height / mDownsampleFactor;
// The following manipulation is to avoid some RenderScript artifacts at the edge.
scaledWidth = scaledWidth - scaledWidth % 4 + 4;
scaledHeight = scaledHeight - scaledHeight % 4 + 4;
if (mBlurredBitmap == null
|| mBlurredBitmap.getWidth() != scaledWidth
|| mBlurredBitmap.getHeight() != scaledHeight) {
mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight,
Bitmap.Config.ARGB_8888);
if (mBitmapToBlur == null) {
return false;
}
mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight,
Bitmap.Config.ARGB_8888);
if (mBlurredBitmap == null) {
return false;
}
}
mBlurringCanvas = new Canvas(mBitmapToBlur);
mBlurringCanvas.scale(1f / mDownsampleFactor, 1f / mDownsampleFactor);
mBlurInput = Allocation.createFromBitmap(mRenderScript, mBitmapToBlur,
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType());
}
return true;
}
protected void blur() {
mBlurInput.copyFrom(mBitmapToBlur);
mBlurScript.setInput(mBlurInput);
mBlurScript.forEach(mBlurOutput);
mBlurOutput.copyTo(mBlurredBitmap);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mRenderScript != null){
mRenderScript.destroy();
}
}
private int mDownsampleFactor;
private int mOverlayColor;
private View mBlurredView;
private int mBlurredViewWidth, mBlurredViewHeight;
private boolean mDownsampleFactorChanged;
private Bitmap mBitmapToBlur, mBlurredBitmap;
private Canvas mBlurringCanvas;
private RenderScript mRenderScript;
private ScriptIntrinsicBlur mBlurScript;
private Allocation mBlurInput, mBlurOutput;
}
Is there any way to modify the BlurringView.java class so the BlurringView xml object can be used like a RelativeView or something similar? I want to be able to have the BlurringView be the parent to other objects.
I need this, because I'm using the BlurringView together with a SlidingUpPanelLayout (https://github.com/umano/AndroidSlidingUpPanel) and the SlidingUpPanelLayout only allows two children for it to function. Thus I can't just overlay items over the BlurringView. I need the BlurringView to be their parent.
Please let me know if you need clarification.
-R
Blockquote Did you try to do an extract method of your constructor, implement the same methon in each of the three default constructors and extend from RelativeLayout?
The RelativeLayout actually have a onDraw method, maybe isn't being called because you didn't invoke the method setWillNotDraw(false), try using that method to trigger the onDraw or use an invalidate() at the end of the constructors.
#astinx answered this question.
All I had to do was change the BlurringView class to extend a RelativeLayout instead of a View. I then called the setWillNotDraw(false) method as well as the invalidate() method in the constructor and now I'm able to populate the BlurringView with children! Magic.
-R
I'm trying to build a view that works like the calendar agenda view (a vertical list of hours that user can select by dragging) but I'm stuck at the part where user begins to start pressing on the screen and dragging his finger over the hour rows to select them. How can I make am overlay representing the selection over the views that represents the hours and expand/shrink it as user drags the selection?
My current interface is composed of a vertical oriented LinearLayout that contains empty TextViews as placeholders that represents the hours of the day.
This is how my screen looks like:
Each green column is the LinearLayout with the TextViews representing the slots. I want to allow the user to start pressing on one of the slots and dragging down to make the selection and while the dragging is in progress to have an overlay that shrinks/expands to reflect the selection.
I've managed to solve it by extending the LinearLayout and hooking into the drawing mechanism like this:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class AvailabilityCalendarColumnLayout extends LinearLayout{
private Drawable overlay;
public AvailabilityCalendarColumnLayout(Context context) {
super(context);
setWillNotDraw(false);
}
public AvailabilityCalendarColumnLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
setWillNotDraw(false);
}
public AvailabilityCalendarColumnLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(overlay != null) {
overlay.draw(canvas);
}
}
public boolean startSelectionOverlay(View startingView) {
if(startingView == null) {
return false;
}
overlay = getResources().getDrawable(R.drawable.overlay);
float[] l = new float[2];
l[0] = startingView.getX();
l[1] = startingView.getY();
int w = startingView.getWidth();
int h = startingView.getHeight();
overlay.setBounds((int) l[0], (int) l[1], (int) l[0] + w, (int) l[1] + h);
invalidate();
return true;
}
private void extendSelectionOverlay(View endView) {
if(endView == null) {
return;
}
float[] l = new float[2];
l[0] = endView.getX();
l[1] = endView.getY();
int w = endView.getWidth();
int h = endView.getHeight();
Rect r = overlay.getBounds();
r.bottom = (int)l[1] + h;
overlay.setBounds(r);
invalidate();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
float[] pos = new float[2];
pos[0] = ev.getX();
pos[1] = ev.getY();
if(action == MotionEvent.ACTION_DOWN && overlay == null) {
View view = getChildViewUnderPosition(pos);
if(view != null) {
startSelectionOverlay(view);
}
}
if(action == MotionEvent.ACTION_MOVE && overlay != null) {
View view = getChildViewUnderPosition(pos);
extendSelectionOverlay(view);
}
if(action == MotionEvent.ACTION_UP && overlay != null) {
endSelectionOverlay();
invalidate();
}
return true;
}
private View getChildViewUnderPosition(float[] pos) {
int num = getChildCount();
View v;
for(int x = 0; x < num; x++) {
v = getChildAt(x);
if(v.getX() <= pos[0] && (v.getX() + v.getWidth()) >= pos[0] && v.getY() <= pos[1] && (v.getY() + v.getHeight()) >= pos[1] && !v.isSelected()) {
return v;
}
}
return null;
}
private void endSelectionOverlay() {
overlay = null;
invalidate();
}
}
I know its possible to paint the background of canvas using
mPaint = new Paint();
mPaint.setColor(Color.RED);
Im just wondering how to i set a permanent background for it. Ive tried using the xml file but nothing happens. Any ideas?
This is the source code of the project, ive been following a tutorial how to do it because im fairly unfamiliar with bitmaps.
Canvas Class
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class GameBoard extends View{
private int mFlagX = -1;
private int mFlagY = -1;
private Bitmap mBitmap = null;
private Bitmap nBitmap = null;
private Paint mPaint = null;
private boolean isFlagHidden = false;
private int mBoundX = -1;
private int mBoundY = -1;
//play with these values to make the app more or less challenging
public final int CLOSER = 50;
public final int CLOSE = 100;
public GameBoard(Context context, AttributeSet aSet) {
super(context, aSet);
//load our bitmap
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.star);
//create a paint brush
mPaint = new Paint();
mPaint.setColor(Color.RED);
}
#Override
public void onDraw(Canvas canvas) {
//initialize
if ((mFlagX < 1) || (mFlagY < 1)) {
mFlagX = (int) (getWidth() / 2) - mBitmap.getWidth() / 2;
mFlagY = (int) (getHeight() / 2) - mBitmap.getHeight() / 2;
mBoundX = (int)getWidth() - mBitmap.getWidth();
mBoundY = (int)getHeight() - mBitmap.getHeight();
}
//draw background
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
//draw the flag
if (!isFlagHidden) {
canvas.drawBitmap(mBitmap, mFlagX, mFlagY, null);
}
}
public void hideTheFlag(){
//randomize flag location
mFlagX = (int) Math.ceil(Math.random() * mBoundX);
mFlagY = (int) Math.ceil(Math.random() * mBoundY);
isFlagHidden = true;
//force redraw
invalidate();
}
public void giveUp(){
isFlagHidden = false;
//force redraw
invalidate();
}
public Indicators takeAGuess(float x, float y) {
//this is our "warm" area
Rect prettyClose = new Rect(mFlagX - CLOSE, mFlagY - CLOSE, mFlagX+mBitmap.getWidth() + CLOSE, mFlagY+mBitmap.getHeight() + CLOSE);
//normalize
if (prettyClose.left < 0) prettyClose.left = 0;
if (prettyClose.top < 0) prettyClose.top = 0;
if (prettyClose.right > mBoundX) prettyClose.right = mBoundX;
if (prettyClose.bottom > mBoundY) prettyClose.bottom = mBoundY;
//this is our "hot" area
Rect reallyClose = new Rect(mFlagX - CLOSER, mFlagY - CLOSER, mFlagX+mBitmap.getWidth() + CLOSER, mFlagY+mBitmap.getHeight() + CLOSER);
//normalize
if (reallyClose.left < 0) reallyClose.left = 0;
if (reallyClose.top < 0) reallyClose.top = 0;
if (reallyClose.right > mBoundX) reallyClose.right = mBoundX;
if (reallyClose.bottom > mBoundY) reallyClose.bottom = mBoundY;
//this is the area that contains our flag
Rect bullsEye = new Rect(mFlagX, mFlagY, mFlagX+mBitmap.getWidth(), mFlagY+mBitmap.getHeight());
//check to see where on the board the user pressed
if (bullsEye.contains((int) x, (int)y)) {
//found it
isFlagHidden = false;
invalidate();
return Indicators.BULLSEYE;
} else if (reallyClose.contains((int) x, (int)y)) {
//hot
return Indicators.HOT;
} else if (prettyClose.contains((int)x, (int)y)) {
//warm
return Indicators.WARM;
} else {
//not even close
return Indicators.COLD;
}
}
}
Game Class
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
public class FindTheStar extends Activity implements OnTouchListener, OnClickListener{
private GameBoard mGameBoard = null;
private boolean isFlagHidden = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_star);
mGameBoard = (GameBoard) findViewById(R.id.Hide_canvas);
mGameBoard.setOnTouchListener(this);
Button b = (Button) findViewById(R.id.the_button);
b.setOnClickListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.Hide_canvas) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (isFlagHidden) {
TextView tv = (TextView)findViewById (R.id.the_label);
switch (mGameBoard.takeAGuess(event.getX(), event.getY())) {
case BULLSEYE:
Button b = (Button) findViewById(R.id.the_button);
isFlagHidden = false;
b.setText("Go Hide!");
tv.setText("You found me!");
tv.setTextColor(Color.GREEN);
break;
case HOT:
tv.setText("You're hot!");
tv.setTextColor(Color.RED);
break;
case WARM:
tv.setText("Getting warm...");
tv.setTextColor(Color.YELLOW);
break;
case COLD:
tv.setText("You're cold.");
tv.setTextColor(Color.BLUE);
break;
}
}
}
return true;
}
return false;
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.the_button) {
TextView tv = (TextView)findViewById (R.id.the_label);
tv.setText("");
Button b = (Button) findViewById(R.id.the_button);
isFlagHidden = !isFlagHidden;
if (isFlagHidden) {
b.setText("Can't find me?");
mGameBoard.hideTheFlag();
} else {
b.setText("Go Hide!");
mGameBoard.giveUp();
}
}
}
}
XML File
<?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">
<TextView
android:id="#+id/the_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
android:layout_marginBottom="10dip"
android:text="Lets Play Hide and Seek!"/>
<Button
android:id="#+id/the_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginBottom="10dip"
android:text="Go Hide!"/>
<app.autismapp.GameBoard
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/Hide_canvas"/>
</LinearLayout>
yes you can set your permanent background using xml layout..i done this by creating two class.
this is my code in MainACtivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final BrushView view=new BrushView(this);
setContentView(R.layout.mylayout);//removed this one if the paint doesnt work
view.setBackgroundResource(R.drawable.background);//to set background
setContentView(view);// to display the background
and my second class
public class PaintView extends View {
private Paint paint = new Paint();
public LayoutParams params;
public PaintView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
i hope it gives you an idea
I have a small test app on Android that is meant to test tracking multitouch input, but I am only ever getting two touches at the same time on my Evo. Does anyone know if this is a limitation to Android or the hardware?
By the way, here's my test class so you can try it out yourself.
import java.util.HashMap;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import android.view.View;
public class PressureView extends View
{
private HashMap<Integer, Spot> mSpots = new HashMap<Integer, Spot>();
private final int[] mColors;
private final Paint mPaint;
public PressureView(Context context)
{
super(context);
mPaint = new Paint();
mPaint.setStyle(Style.FILL);
mColors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA};
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
for(int id : mSpots.keySet())
{
Spot spot = mSpots.get(id);
mPaint.setColor(spot.Color);
canvas.drawCircle(spot.X, spot.Y, spot.Pressure*500, mPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
System.out.println("************************** " + event.getPointerCount() + " Pointers");
for(int i = 0; i < event.getPointerCount(); i++)
{
int id = event.getPointerId(i);
Spot spot = null;
if(mSpots.containsKey(id))
{
spot = mSpots.get(id);
}
else
{
spot = new Spot();
spot.Color = mColors[mSpots.size()];
}
if(event.getAction() == MotionEvent.ACTION_UP) spot.Pressure = 0;
else spot.Pressure = event.getPressure(id);
spot.X = event.getX(id);
spot.Y = event.getY(id);
mSpots.put(id, spot);
}
invalidate();
return true;
}
private class Spot
{
public float X, Y, Pressure;
public int Color;
}
}
It seems that currently all HTC devices only can 2 finger multi-touch, but the Android SDK supports more fingers. E.g. the Galaxy S i9000 has support for more http://www.youtube.com/watch?v=KRCDRXYJBCY .