Първият път, целта беше да се запознаем с това как се прави cutstom view; Целта този път - колко още начина има за това ? От една страна за да ги сравним, като тежест на изпълнение, от друга като възможнисти които ни предсотавят. Приложението днес: DynView.zip; (o) plain, old View(s), revisited; С други думи, отново следваме познатата "рецепта" за собствен View; 1) Наследяваме View, 2) Няма да инстанциираме през код, а през activty .xml -> подходящ конструктор по подразбиране; 3) разбира се onDraw(), за да визуализираме изобщо нещо; Ключово за onDraw(): http://developer.android.com/reference/android/view/View.html#onDraw%28android.graphics.Canvas%29 Drawing Drawing is handled by walking the tree and recording the drawing commands of any View that needs to update. After this, the drawing commands of the entire tree are issued to screen, clipped to the newly damaged area. The tree is largely recorded and drawn in order, with parents drawn before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it before calling back to its onDraw() method. The child drawing order can be overridden with custom child drawing order in a ViewGroup, and with setZ(float) custom Z values} set on Views. To force a view to draw, call invalidate(). С други думи, при промяна в нашето View, Android решава кога да обнови неговото съдържание. Какво правим ако сме нетърпеливи ? invalidate()-ваме :), за да предизвикаме обновяването. StandardPaint.java е класа, реализиращ тази рецепта. Освен изреденото до тук, реализираме допълнителен интерфейс (и негов метод): OnTouchListener/onTouch (http://developer.android.com/reference/android/view/View.OnTouchListener.html); Целта - да, да обработваме touch събития от страна на потребителя. Какво прави в крайна сметка нашият cutom view - зелено кръгче, там където "пипне" потребителят. А ако това са плюсовете на нашето custom view :) кои са му минусите? - предефинирането на onDraw() метода се счита за "бавният" начин за визуализация в Android; Използваме него, ако това което изобразяваме не се нуждае от значителен брой кадри в скунда (fps) или значителен изцислителен ресурс. - всички операции по изобрачяването на извършат в една нишка - тази контролираща нашето Activity (ANR messages); - ако имаме допълнителни нишки, вършещи "тежката" работа за нашият компонент - схемата с invalidate() се променя- изпозлваме postInvalidate(), разбира се трябва си осигурим и видимост на компонента от тази нишка; - принципно onDraw() се използва за бавни (от гледна точка на user interaction) и сравнително статични views; Прекрасно изложение за възможностите ни за 2d графика (вкл. Views) можете да намерите тук: http://developer.android.com/guide/topics/graphics/2d-graphics.html Друга голяма тема, която само докоснахме с този пример е: gesture detection. Имаме достатъчно вградени възможности за това (не се налага да откриваме наново всичко). Изложението можете да намерите тук: http://developer.android.com/training/gestures/index.html (o) 2-ра част - с какво още разполагаме като примитиви ? разбира се SurfaceView и SurfaceHolder; Каква е идеята? - имаме нужда от допълнителен ресурс, изведен в една или няколко други нишки (различни от тази, отговорна за нашето Activity) или много fps. За тази цел е предвиден SurfaceView - тоест приложението няма нужда да чака, докато View йерархията на Android е готова с визуализациите. Рецептата за реализация е почти съсщата. Ключовите моменти са няколко: След наследяването SurfaceView имаме възможност да го управляваме чрез SurfaceHolder (т.е. реализираме допълнителен интерфейс). Управлението ни се заключва между тези два call-back метода: surfaceCreated/surfaceDestroyed При промяна на предоставеният ни surface, получаваме surfaceChanged; Отново "рисуваме" по canvas, който получаваме от SurfaceHolder параметър на горните методи; Тоест нищо кой, знае колко по различно от onDraw(); Ключовите моменти: Трабва да се погрижим за 2-рата нишка, която ще върши същесетвената изчислитела работа; Да осигурим interface на нашето activity към нея, евентулано през SurfaceView наследника; Да съобразим поведението на нишката, спрямо различните етапи от живота на нашето Activity или евентуално потребителският вход; Рисуването става, като заключим, рисуваме и отключим даден canvas обект, предоставен ни от SurfaceHolder; Състоянието на canvas не се запазва, между две последователни итерации, тоест трябва да се погрижим и за това; Класовете в нашето приложение:  DrawingPlace, PaintThread. Да ги разгледаме;