Hvordan kode en 2D tegning med Android Motion Sensors

Som omtalt i min siste Android koding artikkel, en av de pene trekk ved koding for en telefon er muligheten til å bruke sine bevegelsessensorer. Så vel som bare registrerer bevegelse hendelse, som jeg dekket i denne opplæringen, kan du også bruke informasjonen fra sensoren til å endre hva du tegner på skjermen. I denne opplæringen, vil vi se på hvordan å tegne figurer på Android, og på å gjøre litt mer med de opplysninger som er gitt av akselerasjonssensor

Det er to måter å trekke på Android.; via et lerret, eller bruke en tilpasset visning. Denne opplæringen vil se på å bruke en tilpasset visning for å tegne et bevegelig boble på skjermen; se Linux.com for en oppfølging på tegningen med en magnet og oppdager berørings hendelser. Jeg vil ikke gå i for mye detalj om håndtering sensorer; sjekk ut den siste tutorial for detaljert info

Å gjøre en egendefinert visning og boble

Først, la oss strekke Vis å lage en tilpasset View:.

 public class BubbleView strekker Vis { private int diameter; private int x; private int y; private ShapeDrawable boble; offentlig BubbleView (Context kontekst) {super (sammenheng); createBubble (); } Private void createBubble () {x = 200; y = 300; diameter = 100; boble = new ShapeDrawable (ny OvalShape ()); bubble.setBounds (x, y, x + diameter, y + diameter); . bubble.getPaint () SetColor (0xff00cccc); } Beskyttet void onDraw (lerret lerret) {super.onDraw (lerret); bubble.draw (lerret); }} 

Vi bruker ShapeDrawable å lage en oval på tilpasset View. Det er viktig både å sette grensene (boksen innen hvilke oval vil bli trukket, her er det firkantet, så den ovale vil være en sirkel), og maling farge. Så onDraw () er den viktigste metoden for å overstyre - dette er den metoden som vil bli kalt hver gang View er trukket. Her alt vi gjør er å kalle super, deretter tegne boblen

Du kan stille dette som Visning for å bruke med denne koden på din aktivitet:.

 public class BubbleActivity strekker Aktivitet {private BubbleView bubbleView; public void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); bubbleView = new BubbleView (denne); setContentView (bubbleView); }} 

kompilere og kjøre, og du skal se en blå boble i midten av skjermen. (Merk: Jeg fant ut at dette fungerte fint på et håndsett, men ikke på emulator.)

XML Visninger

En alternativ tilnærming til bruk av kode for å sette opp egendefinerte View er å beskrive det i XSL. Her er en enkel XML-fil, res /teikne /circle.xml, for å trekke en blå sirkel på skjermen:?

 < xml version = "1.0" encoding = "utf-8" > < form xmlns: android = "http://schemas.android.com/apk/res/android" android: shape = "oval" > < solid android: color = "# ff00cccc" /> < størrelse android: width = "100dp" android: height = "100dp" /> < /form > 

Å kalle dette fra aktivitets, må du bruke litt mer kode enn du gjør når du utvider Vis:

 privat LinearLayout layout; public void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); layout = new LinearLayout (denne); Imageview i = ny Imageview (dette); i.setImageResource (R.drawable.circle); i.setAdjustViewBounds (true); i.setLayoutParams (nye Gallery.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); layout.addView (i); layout.setGravity (Gravity.CENTER); setContentView (layout);} 

Dette setter opp en ny layout og Imageview, og legger bildet definert av filen res /teikne /circle.xml til Imageview. setAdjustViewBounds () setter Imageview grenser til det samme som størrelsen på teikne. Vi satt layout parametere å pakke innholdet, og tilsett Imageview til layout. Kjør dette, og du vil se en solid sirkel øverst til venstre på skjermen. For å sette det i midten av skjermen, legger du til linjen

 layout.setGravity (Gravity.CENTER); 

Ved hjelp av XML, du kan også sette opp noen ryddig grafiske effekter, som dette skygge circl: < ? br>

 < xml version = "1.0" encoding = "UTF-8" > < shape xmlns: android = "http://schemas.android.com/apk/res/android" android: forme = "oval" > < gradient android: startColor = "# ff0000cc" android: endColor = "# ff00cccc" android: type = "radial" android: gradientRadius = "100" /> < størrelse android: width = "200dp" android: height = "200dp" /> < /form > 

Men dette er egentlig bare egnet for en statisk form, mens vi ønsker en flytting av en. Så vi vil holde med vår skikk Vis klasse.

Flytte med sensoren

Nå har vi vår egendefinert visning med en boble i det, er neste jobb å ta en sensor og gjøre ball flytte med akselerometer. La oss gjøre noe arbeid med BubbleActivity:

 public class BubbleActivity strekker aktivitet implementerer SensorEventListener {private SensorManager manager; private BubbleView bubbleView; private Sensor Accel; public void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); bubbleView = new BubbleView (denne); setContentView (bubbleView); Lederen = (SensorManager) getSystemService (SENSOR_SERVICE); Accel = manager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); manager.registerListener (dette, Accel, SensorManager.SENSOR_DELAY_GAME); } Public void onAccuracyChanged (Sensor sensor, int nøyaktighet) {//gjør ikke noe; vi ikke bryr} public void onSensorChanged (SensorEvent event) {bubbleView.move (event.values ​​[0], event.values ​​[1]); bubbleView.invalidate (); } Beskyttet void onResume () {super.onResume (); manager.registerListener (dette, Accel, SensorManager.SENSOR_DELAY_GAME); } Beskyttet void onPause () {super.onPause (); manager.unregisterListener (denne); }} 

Som per den siste opplæringen, utvider vi SensorEventListener, som betyr å implementere onAccuracyChanged () og onSensorChanged (). Vi får også SensorManager i onCreate (), ta tak i akselerometer, og registrere lytteren. Det er viktig å huske å avregistrere det i onPause () og reregister i onResume (), for å unngå å kjøre rett gjennom batteriet

Når noe skjer, har SensorEvent tre verdier:. X, y og z (akser er definert i API). Vi passerer x- og y av dem til BubbleView. La oss se atBubbleView.move ():

 beskyttet void flytt (float f, float g) {x = (int) (x + f); y = (int) (y + g); bubble.setBounds (x, y, x + diameter, y + diameter);} 

Hvis du prøver å kjøre dette nå, vil du legge merke til at Vis knipser fra liggende til stående når du flytter enheten. For å unngå dette, redigere AndroidManifest.xml å se slik ut:

 ... < aktivitet android: ". BubbleActivity" name = android: screenOrientation = "portrett" android: label = "@ streng /title_activity_bubble" > ... 

Kjør igjen, og du vil se det fungerer som forventet

Finne midten og kantene av skjermen

Vi bruker hardkodede verdier for. startpunktet av boblen, men ideelt sett vil det begynne i midten av skjermen. Dessverre, koordinerer 2D starte fra øverste venstre hjørne av skjermen, så vi må finne skjermstørrelsen enhet:

 private int bredde; private int høyde, private void createBubble () {WindowManager wm = (WindowManager) ctx.getSystemService (Context.WINDOW_SERVICE); Skjerm skjerm = wm.getDefaultDisplay (); Point size = nytt punkt (); display.getSize (størrelse); width = (size.x) /2; height = (size.y) /2; x = bredde; y = høyde; diameter = 100; boble = new ShapeDrawable (ny OvalShape ()); bubble.setBounds (x, y, x + diameter, y + diameter); . bubble.getPaint () SetColor (0xff74AC23);} 

Dette krever API 13; Hvis du heller vil feste med et lavere API, kan du bruke getWidth () og getHeight () metoder i stedet, som nå er foreldet.

Du vil også legge merke til at boblen driver utenfor skjermen. Eksperimenter med koden litt selv (logglinjer kan være nyttig) for å finne en måte å unngå det. Man kan også bruke z-verdien for SensorEvent (event.values ​​[2]) for å avgrense bevegelsen av boblen litt videre. Som alltid, jo mer du spiller rundt med koden selv, jo mer vil du lære om hvordan det hele fungerer. Anmeldelser