Custom views
satya - Thu Oct 18 2012 09:04:14 GMT-0400 (Eastern Daylight Time)
Here is how you would save the state of a view
public Bundle saveState() {
Bundle map = new Bundle();
map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
map.putInt("mDirection", Integer.valueOf(mDirection));
map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
map.putLong("mScore", Long.valueOf(mScore));
map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
return map;
}
satya - Thu Oct 18 2012 09:05:00 GMT-0400 (Eastern Daylight Time)
Here is how you would retrieve it
public void restoreState(Bundle icicle) {
setMode(PAUSE);
mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
mDirection = icicle.getInt("mDirection");
mNextDirection = icicle.getInt("mNextDirection");
mMoveDelay = icicle.getLong("mMoveDelay");
mScore = icicle.getLong("mScore");
mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
}
satya - Thu Oct 18 2012 09:09:07 GMT-0400 (Eastern Daylight Time)
Here is how you respond to keys
@Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
if (mMode == READY | mMode == LOSE) {
/*
* At the beginning of the game, or the end of a previous one,
* we should start a new game.
*/
initNewGame();
setMode(RUNNING);
update();
return (true);
}
if (mMode == PAUSE) {
/*
* If the game is merely paused, we should just continue where
* we left off.
*/
setMode(RUNNING);
update();
return (true);
}
if (mDirection != SOUTH) {
mNextDirection = NORTH;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (mDirection != NORTH) {
mNextDirection = SOUTH;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
if (mDirection != EAST) {
mNextDirection = WEST;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if (mDirection != WEST) {
mNextDirection = EAST;
}
return (true);
}
return super.onKeyDown(keyCode, msg);
}
satya - Thu Oct 18 2012 09:13:12 GMT-0400 (Eastern Daylight Time)
Here is how your custom view reads xml attributes
public TileView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
a.recycle();
}
public TileView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
a.recycle();
}
satya - Thu Oct 18 2012 09:15:12 GMT-0400 (Eastern Daylight Time)
Here is a note on custom attributes
satya - Thu Oct 18 2012 09:16:28 GMT-0400 (Eastern Daylight Time)
Here is how you could setup the xml
<com.ai.android.book.apptemplate2.MyTextView
android:id="@+id/custom_text_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Debut Text Appears here"
apptemplate:custom_text="Custom Hello"
/>
satya - Thu Oct 18 2012 09:36:44 GMT-0400 (Eastern Daylight Time)
A bare bones custom view
public class CircleView
extends View
{
public CircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public static String tag="CircleView";
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w,h,oldw,oldh);
Log.d(tag,"onSizeChanged");
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(tag,"onDraw called");
}
}
satya - Thu Oct 18 2012 09:41:53 GMT-0400 (Eastern Daylight Time)
This is a better way of dealing with multiple constructors
public SnakeView(Context context, AttributeSet attrs) {
super(context, attrs);
initSnakeView();
}
public SnakeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initSnakeView();
}
satya - Thu Oct 18 2012 09:42:05 GMT-0400 (Eastern Daylight Time)
Notice the 'init' method
Notice the 'init' method
satya - Thu Oct 18 2012 09:55:23 GMT-0400 (Eastern Daylight Time)
Here is the view api
satya - Thu Oct 18 2012 09:55:54 GMT-0400 (Eastern Daylight Time)
On constructors
There is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. The second form should parse and apply any attributes defined in the layout file.
satya - Thu Oct 18 2012 09:57:54 GMT-0400 (Eastern Daylight Time)
Use a constructor like this if you want to instantiate your view directly from code
public CircleView(Context context) {
super(context);
}
satya - Thu Oct 18 2012 10:00:33 GMT-0400 (Eastern Daylight Time)
Here is the canvas api
satya - Thu Oct 18 2012 10:26:01 GMT-0400 (Eastern Daylight Time)
Here is a nice Arcs.java from the android sample code
public class Arcs extends GraphicsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private Paint[] mPaints;
private Paint mFramePaint;
private boolean[] mUseCenters;
private RectF[] mOvals;
private RectF mBigOval;
private float mStart;
private float mSweep;
private int mBigIndex;
private static final float SWEEP_INC = 2;
private static final float START_INC = 15;
public SampleView(Context context) {
super(context);
mPaints = new Paint[4];
mUseCenters = new boolean[4];
mOvals = new RectF[4];
mPaints[0] = new Paint();
mPaints[0].setAntiAlias(true);
mPaints[0].setStyle(Paint.Style.FILL);
mPaints[0].setColor(0x88FF0000);
mUseCenters[0] = false;
mPaints[1] = new Paint(mPaints[0]);
mPaints[1].setColor(0x8800FF00);
mUseCenters[1] = true;
mPaints[2] = new Paint(mPaints[0]);
mPaints[2].setStyle(Paint.Style.STROKE);
mPaints[2].setStrokeWidth(4);
mPaints[2].setColor(0x880000FF);
mUseCenters[2] = false;
mPaints[3] = new Paint(mPaints[2]);
mPaints[3].setColor(0x88888888);
mUseCenters[3] = true;
mBigOval = new RectF(40, 10, 280, 250);
mOvals[0] = new RectF( 10, 270, 70, 330);
mOvals[1] = new RectF( 90, 270, 150, 330);
mOvals[2] = new RectF(170, 270, 230, 330);
mOvals[3] = new RectF(250, 270, 310, 330);
mFramePaint = new Paint();
mFramePaint.setAntiAlias(true);
mFramePaint.setStyle(Paint.Style.STROKE);
mFramePaint.setStrokeWidth(0);
}
private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,
Paint paint) {
canvas.drawRect(oval, mFramePaint);
canvas.drawArc(oval, mStart, mSweep, useCenter, paint);
}
@Override protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
drawArcs(canvas, mBigOval, mUseCenters[mBigIndex],
mPaints[mBigIndex]);
for (int i = 0; i < 4; i++) {
drawArcs(canvas, mOvals[i], mUseCenters[i], mPaints[i]);
}
mSweep += SWEEP_INC;
if (mSweep > 360) {
mSweep -= 360;
mStart += START_INC;
if (mStart >= 360) {
mStart -= 360;
}
mBigIndex = (mBigIndex + 1) % mOvals.length;
}
invalidate();
}
}
}
satya - Thu Oct 18 2012 10:47:26 GMT-0400 (Eastern Daylight Time)
html color codes
satya - Thu Oct 18 2012 10:48:00 GMT-0400 (Eastern Daylight Time)
Figuring out html color
satya - Thu Oct 18 2012 10:51:05 GMT-0400 (Eastern Daylight Time)
Here are named colors
satya - Thu Oct 18 2012 16:16:49 GMT-0400 (Eastern Daylight Time)
Keep in mind: setColor is a surprise, it contains alpha too
Set the paint's color. Note that the color is an int containing alpha as well as r,g,b. This 32bit value is not premultiplied, meaning that its alpha can be any value, regardless of the values of r,g,b. See the Color class for more details.
satya - Thu Oct 18 2012 16:17:34 GMT-0400 (Eastern Daylight Time)
Here is the api for android.graphics.Color
satya - Thu Oct 18 2012 16:19:28 GMT-0400 (Eastern Daylight Time)
Here is the overview of Color
The Color class defines methods for creating and converting color ints. Colors are represented as packed ints, made up of 4 bytes: alpha, red, green, blue. The values are unpremultiplied, meaning any transparency is stored solely in the alpha component, and not in the color components. The components are stored as follows (alpha << 24) | (red << 16) | (green << 8) | blue. Each component ranges between 0..255 with 0 meaning no contribution for that component, and 255 meaning 100% contribution. Thus opaque-black would be 0xFF000000 (100% opaque but no contributions from red, green, or blue), and opaque-white would be 0xFFFFFFFF"
satya - Thu Oct 18 2012 16:23:18 GMT-0400 (Eastern Daylight Time)
Examples
BLACK: 0xff000000
alpha is FF, all 0s
BLUE: 0xff0000ff
Transparent: 0x00000000
satya - Mon Oct 22 2012 09:51:57 GMT-0400 (Eastern Daylight Time)
onSizeChanged and invalidate in Android
onSizeChanged and invalidate in Android
satya - Mon Oct 22 2012 09:57:56 GMT-0400 (Eastern Daylight Time)
onSizeChanged
onSizeChanged
Search Google for: onSizeChanged
Search Android Developers Group for: onSizeChanged
Search Android Beginers Group for: onSizeChanged
satya - Mon Oct 22 2012 10:00:40 GMT-0400 (Eastern Daylight Time)
Here is a bit of thought generating post
satya - Mon Oct 22 2012 10:03:39 GMT-0400 (Eastern Daylight Time)
Here is a comment from Romain
onSizeChanged() is invoked as part of the layout pass, and you cannot/should not requestLayout() during a layout pass. It is correct to post a requestLayout() on the event queue to indicate that you have changed the View hierarchy during a layout pass.
satya - Mon Oct 22 2012 10:05:12 GMT-0400 (Eastern Daylight Time)
Here is apparently how you do that
post(new Runnable() {
public void run() {
requestLayout();
}
});
satya - Mon Oct 22 2012 10:05:31 GMT-0400 (Eastern Daylight Time)
invalidate during a layout phase in android
invalidate during a layout phase in android
satya - Mon Oct 22 2012 10:09:15 GMT-0400 (Eastern Daylight Time)
is onSizeChanged always followed by an OnDraw?
is onSizeChanged always followed by an OnDraw?
satya - Mon Oct 22 2012 11:03:10 GMT-0400 (Eastern Daylight Time)
top, left, bottom, right are relative to its parent
top, left, bottom, right are relative to its parent
satya - Mon Oct 22 2012 11:33:27 GMT-0400 (Eastern Daylight Time)
Notes on onSizeChanged()
1. Triggered by layout phase
2. specifically called by layout() of the base view
3. More specifically by setFrame() of the base view
4. will not be called if there is no change to the size
5. invalidate of the base view called as well
6. base view has recorded its size before calling onsizechanged
7. base view has an empty implementation for this method
8. onDraw will be triggered because of invalidate in a subsequent
draw phase
9. it is wrong to call requestLayout because it is already in a
layout phase. if needed post to a thread to call it
10. You can choose to use measurements from the base view if you choose
satya - Mon Oct 22 2012 13:19:57 GMT-0400 (Eastern Daylight Time)
onmeasure and wrap_content
onmeasure and wrap_content
satya - Mon Oct 22 2012 13:51:08 GMT-0400 (Eastern Daylight Time)
Why is wrap_content taking all the remaining space?
Why is wrap_content taking all the remaining space?
Search for: Why is wrap_content taking all the remaining space?
satya - Mon Oct 22 2012 17:19:39 GMT-0400 (Eastern Daylight Time)
Here is another fellow having the same problem
satya - Mon Oct 22 2012 17:21:49 GMT-0400 (Eastern Daylight Time)
onmeasure getDefaultSize wrap_content
onmeasure getDefaultSize wrap_content
satya - Tue Oct 23 2012 23:02:32 GMT-0400 (Eastern Daylight Time)
How to save android view state?
How to save android view state?
satya - Tue Oct 23 2012 23:13:26 GMT-0400 (Eastern Daylight Time)
Here is an indepth conversation about this subject