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

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

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

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

Search for: html color codes

satya - Thu Oct 18 2012 10:48:00 GMT-0400 (Eastern Daylight Time)

Figuring out html color

Figuring out html color

satya - Thu Oct 18 2012 10:51:05 GMT-0400 (Eastern Daylight Time)

Here are named colors

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

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

Search for: 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

Search Google Code for: onSizeChanged

Search Android Issues Database for: onSizeChanged

satya - Mon Oct 22 2012 10:00:40 GMT-0400 (Eastern Daylight Time)

Here is a bit of thought generating post

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

Search for: 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?

Search for: 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

Search for: 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

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

Search for: 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?

Search for: 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

Here is an indepth conversation about this subject