1 / 13

My own View Android development

My own View Android development. Maarten Pennings 2011 oct 14. Views. User Interface elements are known as Views Button TextView … I have written my own view NumGridView That can be used from XML layout in activity. NumGridView. My app contains a 5x5 grid with numbers

alagan
Download Presentation

My own View Android development

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. My own ViewAndroid development Maarten Pennings 2011 oct 14

  2. Views • User Interface elements are known as Views • Button • TextView • … • I have written my own view • NumGridView • That can be used from XML layout in activity

  3. NumGridView • My app contains a 5x5 grid with numbers • This is my NumGridView drawing itself • When you press a grid cell it is incremented • This is activity specific (coded in a listener)

  4. Activity code is simple publicclassNumGridActivityextendsActivity { NumGridView mNumGridView; OnCellTouchListener mNumGridView_OnCellTouchListener= new OnCellTouchListener() { @Override public void onCellTouch( NumGridView v, int x, inty ) { v.setCell(x, y, v.getCell(x,y)+1 ); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mNumGridView= (NumGridView)findViewById(R.id.numgridview); mNumGridView.setOnCellTouchListener(mNumGridView_OnCellTouchListener); } }

  5. Activity layout has minor twists <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:numgrid="http://schemas.android.com/apk/res/nl.fampennings.numgrid" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hint" android:textSize="10mm" /> <nl.fampennings.numgrid.NumGridView android:id="@+id/numgridview" android:layout_width="fill_parent" android:layout_height="fill_parent" numgrid:cellCountX="5" numgrid:cellCountY="5" /> </LinearLayout>

  6. Required: file attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="NumGridView"> <attr name="stretch" format="boolean" /> <attr name="cellCountX" format="integer" min="1" /> <attr name="cellCountY" format="integer" min="1" /> </declare-styleable> </resources>

  7. Required: file NumGridView.java Resides in same package packagenl.fampennings.numgrid; import android.view.View; ... publicclass NumGridView extends View { // Member variables ... public NumGridView (Context context, AttributeSet attrs) {...} public void setCell (int x, int y, int v) {...} public int getCell (int x, int y ) {...} @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {...} @Override protected void onDraw (Canvas canvas) {...} // OnCellTouchListener ... } Extends basic View class Lazy: only implemented constructor for XML Setter and Getter for cell value “Mandatory”overrides Cell touch call-back

  8. Constructor Call parent constructor publicNumGridView(Context context, AttributeSet attrs) { super(context, attrs); ... // Get the xml attributes TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumGridView); mStretch = a.getBoolean(R.styleable.NumGridView_stretch, false); mCellCountX = a.getInt(R.styleable.NumGridView_cellCountX, 8); mCellCountY = a.getInt(R.styleable.NumGridView_cellCountY, 8); a.recycle(); // Setup the grid cells mCells= new int[mCellCountX][mCellCountY]; for(int y=0; y<mCellCountY; y++) for(int x=0; x<mCellCountX; x++) mCells[x][y]= 0; } Retrieve styled attribute information Lookup the attributes(pass default in case attribute is not set) “free”! Create the actual grid data array, and fill with zero’s

  9. Setter and Getter Sort of assert(don’t know if it’s wise) publicvoid setCell(int x, int y, int v) { if( ! (0<=x && x<mCellCountX) ) thrownew IllegalArgumentException("setCell: x coordinate out of range"); if( ! (0<=y && y<mCellCountY) ) thrownew IllegalArgumentException("setCell: y coordinate out of range"); mCells[x][y]= v; invalidate(); } public int getCell(int x, int y ) { if( ! (0<=x && x<mCellCountX) ) thrownew IllegalArgumentException("setCell: x coordinate out of range"); if( ! (0<=y && y<mCellCountY) ) thrownew IllegalArgumentException("setCell: y coordinate out of range"); return mCells[x][y]; } Set the value Force a re-draw Get the value

  10. onMeasure The renderer calls us with onMeasure to ask how big we want to be (sometimes passing max sizes). We must respond by calling setMeasuredDimension. @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Extract the Ms (MesaureSpec) parameters int widthMsMode = MeasureSpec.getMode(widthMeasureSpec); int widthMsSize = MeasureSpec.getSize(widthMeasureSpec); int heightMsMode = MeasureSpec.getMode(heightMeasureSpec); int heightMsSize = MeasureSpec.getSize(heightMeasureSpec); // Determine preferred size mCellWidth = (int)Math.floor(widthMsSize / mCellCountX ); mCellHeight= (int)Math.floor(heightMsSize / mCellCountY ); mOffsetX= ( widthMsSize - mCellWidth*mCellCountX ) / 2; mOffsetY= ( heightMsSize - mCellHeight*mCellCountY ) / 2; // Must declare my size setMeasuredDimension( mOffsetX + mCellCountX*mCellWidth + mOffsetX, mOffsetY + mCellCountY*mCellHeight + mOffsetY ); } Just a fragment; real code is harder

  11. onDraw The renderer passes us the canvas to draw ourselves on @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); ... // Draw all cells for(int y=0; y<mCellCountY; y++) { for(int x=0; x<mCellCountX; x++) { // Get cell data int v = mCells[x][y]; int dx= x*mCellWidth+mOffsetX; int dy= y*mCellHeight+mOffsetY; // Draw a rectangle in the cell canvas.drawRect( new Rect(dx+1,dy+1,dx+mCellWidth-2,dy+mCellHeight-2), mPaintBg); // Draw value canvas.drawText( ""+v, dx+cx, dy+cy, mPaintFg); } } } We loop over all cells, … … draw a box on the canvas, … … and draw the cell value centered in the box The ‘paint’ (created in onCreate) is our pencil (color, font style, typeface, …)

  12. onCellTouchListener A class local interface definition for our listener publicinterface OnCellTouchListener { void onCellTouch(NumGridView v, int x, int y); } protected OnCellTouchListener mOnCellTouchListener; public void setOnCellTouchListener(OnCellTouchListener listener) { mOnCellTouchListener = listener; } @Override public boolean dispatchTouchEvent(MotionEvent event) { // First dispatch calls to our cell touch listener... if( mOnCellTouchListener!=null ) { int x=(int)(event.getX()) - mOffsetX; int y=(int)(event.getY()) - mOffsetY; if( 0<=x && x<mCellWidth*mCellCountX && 0<=y && y<mCellHeight*mCellCountY ) { // Touch was on cell (not on padding area) mOnCellTouchListener.onCellTouch(this,x/mCellWidth,y/mCellHeight); } } // ... next dispatch calls from the super class return super.dispatchTouchEvent(event); } One function: touch on x,y The member variable to store the listener The Setter for the listener The NumGridView does not register itself as listener, it overrides the dispatcher. This allows our customers to register an event listener for raw coordinates. map raw (x,y) to cell (x,y) Call listener (if set, if touch was on cell) Let super class do rest of dispatching

  13. The END

More Related