Het ontwikkelen van widgets voor het Android-platform omvat een iets andere reeks taken dan standaard app-ontwikkeling. In deze reeks zelfstudies werken we aan het ontwikkelen van een aanpasbare analoge klokwidget. De klok is gebaseerd op de Android AnalogClock-klasse en aangepast met uw eigen grafische afbeeldingen.
Tot nu toe hebben we in deze serie de widget in XML en Java ontworpen en geïmplementeerd en hebben we een werkende klokwidget die de gebruiker aan zijn startscherm kan toevoegen. In dit laatste deel van de serie gaan we de basisgebruikersconfiguratie implementeren. In deel 2 hebben we meerdere klokontwerpen gemaakt, dus nu zullen we de gebruiker toestaan om tussen deze ontwerpen te kiezen.
Dit is deel 4 van 4 in een serie over het bouwen van een aanpasbare Android analoge klok Widget in vier tutorials:
Het bouwen van gebruikersconfiguraties in onze widget-app gaat een nieuwe Java-activiteitsklasse met zich meebrengen, die de selectie van keuzes aan de gebruiker presenteert. Wanneer de gebruiker een ontwerp selecteert, werken we het uiterlijk van de widget bij en slaan we de gebruikerskeuze op in de gedeelde voorkeuren van de toepassing. We breiden ook de widgetklasse uit om gebruikersklikken op de widget te verwerken en om te lezen in de Gemeenschappelijke voorkeuren voor de keuze van de gebruiker. Naast het werken met deze twee Java-bestanden, maken we een nieuw waardenbestand en een XML-lay-outbestand voor de geselecteerde activiteit samen met enkele afbeeldingen om daarin weer te geven.
Laten we eerst wat code aan de widgetklasse toevoegen om klikken van gebruikers te detecteren. In de klasse "ClockWidget", in de "if" -instructie in de "onReceive" -methode, na de regel waarin we het Remote Views-object hebben opgehaald, voegt u de volgende code toe om een intentie voor de chooser-activiteit te maken die we gaan gebruiken:
Intent choiceIntent = new Intent (context, ClockChoice.class);
Maak je geen zorgen over de Eclipse-fouten voor nu, ze zullen verdwijnen wanneer we de nieuwe Activity-klasse in de volgende stap maken. Maak na deze regel als volgt een Pending Intent:
PendingIntent clickPendIntent = PendingIntent.getActivity (context, 0, choiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Het starten van activiteiten op widget klikken is een beetje anders, zoals u kunt zien. Merk op dat we het Context-object en een verwijzing naar de nieuwe Intent doorgeven. Voeg nu de volgende code toe en geef aan dat de Pending Intent moet worden gestart wanneer op de widget wordt geklikt:
views.setOnClickPendingIntent (R.id.custom_clock_widget, clickPendIntent);
We specificeren de widget door te verwijzen naar de ID van de bovenliggende lay-out in het XML-bestand "clock_widget_layout". We moeten de Remote Views gebruiken om naar de items in de gebruikersinterface te verwijzen omdat we in een widgetklasse zijn in plaats van in een Activity Class. Later zullen we meer code aan deze klasse toevoegen.
Nu voor de activiteit waarin we gebruikers een ontwerp laten kiezen. Maak een nieuwe klasse in uw project door met de rechtermuisknop te klikken of de bronpakketmap te selecteren en "Bestand" te kiezen - selecteer vervolgens "Nieuw", "Klasse" en voer "Klokkeuze" in als de klassenaam. Eclipse opent de nieuwe klas wanneer u op Voltooien klikt. Vergeet niet dat we deze activiteit hebben opgenomen in het Manifest-projectbestand in deel 1.
Maak van je nieuwe klas een activiteit en een die de klikken van gebruikers verwerkt door de openingslijn als volgt uit te breiden:
public class ClockChoice breidt activiteit uit OnClickListener
Nogmaals, negeer eventuele foutmeldingen, ze verschijnen totdat we de "onClick" -methode aanbieden. U hebt de volgende importinstructies nodig:
import android.app.Activity; import android.view.View.OnClickListener;
Geef de activiteit "onCreate" binnen de klasse als volgt:
public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.clock_choice);
We zullen het lay-outbestand in de volgende stap maken. U heeft nog een import nodig:
import android.os.Bundle;
Later zullen we meer code aan deze klas toevoegen.
Laten we de lay-out maken die we hebben opgegeven in de bovenstaande klasse Activiteit. Maak een nieuw lay-outbestand door met de rechtermuisknop te klikken of de map "res / layout" te selecteren en "Bestand" te kiezen. Klik vervolgens op "Nieuw", "Bestand" en voer "clock_choice.xml" in om overeen te stemmen met de referentie in de bovenstaande code.
Wanneer Eclipse het bestand opent, selecteert u het tabblad "clock_choice.xml" om de code te bewerken. Voer de volgende indelingsschema's in uw bestand in:
Het ontwerp bevat een lineaire lay-out in een bladerweergave. Voeg binnen de Lineaire lay-out eerst wat informatieve tekst toe als volgt:
Voeg de String-resource hier aan uw "strings.xml" -bestand toe - zorg ervoor dat u deze in beide exemplaren van het strings-bestand opneemt, in "values" en "values-v14":
Kies een optie:
Nu gaan we een afbeelding weergeven voor elk klokontwerp. Deze afbeeldingen gaan fungeren als knoppen waarop gebruikers kunnen drukken bij het selecteren van een ontwerp. Maak nu uw foto's, onthoud dat u voor elke dichtheid verschillende versies moet gebruiken. Als je je eigen nog niet wilt maken, kun je de afbeeldingen gebruiken in de downloadlink onderaan de tutorial - hier zijn de versies met gemiddelde dichtheid van elk:
Sla elke versie van uw afbeeldingen op in de beschrijfbare mappen voor uw app en onthoud dat u dezelfde namen in elke map met dichtheid gebruikt.
Ga nu terug naar uw "clock_choice" lay-out XML-bestand. Voeg een Afbeeldingsknop toe voor elk ontwerp dat u gebruikt, met het volgende voor de drie voorbeeldontwerpen die we hebben gebruikt, na de Tekstweergave:
Er zijn verschillende punten om op te merken. Merk allereerst op dat elke Image Button een ID heeft met dezelfde syntaxis, maar een incrementerend geheel getal aan het einde - we zullen dit gebruiken om de ontwerpen in Java te herhalen, dus als je meer dan drie ontwerpen toevoegt, zorg er dan voor dat je ze itereert getallen, zoals "ontwerp_3" enz. Afgezien van de ontwerpkenmerken, geeft elk element ook de relevante tekenbare bron aan, dus verander deze als de beeldbestanden die u zojuist hebt gemaakt, verschillende namen hebben. Ten slotte verwijzen de kenmerken van de beschrijving van de inhoud naar tekenreeksen, dus voeg ze als volgt toe aan de "strings.xml" -bestanden in zowel de mappen "values" en "values-v14":
Standaard ontwerp Steen ontwerp Metalen ontwerp
Wijzig deze beschrijvingen indien nodig om uw eigen ontwerpen aan te passen.
Laten we Android-thema's gebruiken om bepaalde aspecten van het uiterlijk van de kiezer te automatiseren. Open het manifestbestand Manifest en breid het element dat de activiteit Klokkiezer uitmaakt als volgt uit:
Door het dialoogvensterthema toe te voegen, wordt de activiteit overlay op het startscherm weergegeven. Dit komt overeen met de voorbeeldontwerpen die we in deze zelfstudieserie hebben gebruikt:
Dit is wat er verschijnt als de gebruiker op de widget klikt. Als het display van het apparaat te klein is om alle drie de ontwerpen te bevatten, zullen ze scrollen terwijl de lay-out een Scroll View gebruikt. Wanneer de gebruiker een ontwerp selecteert, wordt de weergave van de widget bijgewerkt en deze keuzeactiviteit verdwijnt.
Het spreekt voor zich dat u wellicht het aantal mogelijke ontwerpen in uw klokwidgets-app wilt wijzigen. Om dit proces gemakkelijker te maken, gaan we onze Java-code het aantal ontwerpen dynamisch laten lezen. Voor dit doel gaan we een numerieke waarde gebruiken om het aantal ontwerpen dat we gebruiken bij te houden. Maak een nieuw bestand in elk van uw mappen met twee waarden, klik met de rechtermuisknop of selecteer achtereenvolgens elke map en kies "Bestand" en vervolgens "Nieuw", "Bestand" en voer "numbers.xml" in als bestandsnaam.
Selecteer het tabblad "numbers.xml" en voer de volgende code in uw nieuwe bestand in:
3
Wijzig het cijfer als u een ander aantal ontwerpen gebruikt en zorg ervoor dat de waarde overeenkomt met het aantal afbeeldingenknoppen dat u hebt opgenomen in de lay-out en het aantal analoge klokelementen dat u in uw widgetlay-out hebt. Vergeet niet dat u een exemplaar van het bestand "numbers.xml" in beide waardenmappen nodig hebt, dus kopieer en plak het indien nodig.
Als u het aantal ontwerpen dat u gebruikt op enig moment wijzigt, moet u de waarde in het bestand "numbers.xml" wijzigen, elk ontwerp toevoegen als een Analog Clock-element in het bestand "clock_widget_layout" van de app en een Afbeeldingsknop voor elk ontwerp in de kiezer Activiteit lay-outbestand.
Laten we omgaan met gebruikersinteractie met de selectie van klokontwerpen. Open uw "ClockChoice" activiteitsbestand. Binnen de klasse, vóór de methode "onCreate", voegt u de volgende instantievariabelen toe:
// aantal ontwerpen private int numDesigns; // afbeeldingsknoppen voor elk ontwerp privé ImageButton [] designBtns; // identifiers voor elk klokelement private int [] -ontwerpen;
We zullen deze variabelen gebruiken om de verschillende ontwerpen te doorlopen. Voeg nog een import toe:
importeer android.widget.ImageButton;
Gebruik binnen de methode "onCreate", na de bestaande code, de variabele om het aantal klokontwerpen bij te houden, als volgt:
numDesigns = this.getResources (). getInteger (R.integer.num_clocks);
Hier halen we de waarde op in het XML-bestand dat we eerder hebben gemaakt - we kunnen deze waarde gebruiken als referentie bij het doorzoeken van de ontwerpen. Start vervolgens de arrays voor de ontwerpknoppen en klokelementen:
designBtns = new ImageButton [numDesigns]; designs = new int [numDesigns];
De eerste array verwijst naar de Image Buttons die we gebruiken in deze Chooser Activity om de keuze van de gebruiker te detecteren. De tweede array gaat verwijzingen naar de Analoge klokelementen opslaan voor elk ontwerp in het widgetlay-outbestand zelf.
Voeg nu een lus toe om de ontwerpen te herhalen:
voor (int d = 0; dZoek in de loop een verwijzing op naar elk Analog Clock-element in de widgetlay-out:
ontwerpen [d] = this.getResources (). getIdentifier ("AnalogClock" + d, "id", getPackageName ());Als u terugkijkt op het bestand "clock_widget_layout", ziet u dat elk Analog Clock-element een ID heeft dat bestaat uit "AnalogClock" gevolgd door een oplopend geheel getal - we gebruiken dit hier om een verwijzing naar elk met behulp van de lusteller op te halen. Zoek vervolgens, nog steeds binnen de lus, de ID-waarden op voor de Image Buttons in de Chooser Activity-indeling:
designBtns [d] = (ImageButton) findViewById (this.getResources (). getIdentifier ("ontwerp _" + d, "id", getPackageName ()));Hier gebruiken we "findViewById" om een verwijzing naar het relevante Image Button-element te krijgen, waarbij de ID wordt doorgegeven die "design_" omvat, gevolgd door het incrementerende gehele getal. Stel nu de kliklistener voor elk van deze knoppen in zodat we klikken in deze Activiteitsklasse kunnen verwerken. Terwijl je nog in de lus zit:
designBtns [d] .setOnClickListener (deze);Nu kunnen we doorgaan met de klikmethode voor de ontwerpknoppen. Na de methode "onCreate" in de klasse "ClockChoice", voegt u als volgt een "onClick" -methode toe:
openbare ongeldig onClick (View v)Voeg de volgende import toe:
import android.view.View;In de "onClick" -methode moeten we eerst bepalen op welke knop de gebruiker heeft gedrukt. Voeg hiertoe de volgende lus toe aan de methode:
int picked = -1; voor (int c = 0; cHier controleren we de aangeklikte View ID tegen de ID's die we hebben opgeslagen in de Image Button-array. Wanneer de lus wordt afgesloten, hebben we de gekozen index opgeslagen in een lokale variabele. Na de lus slaat u een verwijzing op naar de ID voor het gekozen analoge klokelement:
int pickedClock = ontwerpt [geplukt];Nu moeten we een verwijzing naar de widgetlay-outelementen krijgen, waarvoor we de Remote Views-weergave nodig hebben en de widgetlay-out als referentie doorgeven:
RemoteViews remoteViews = nieuwe RemoteViews (this.getApplicationContext (). GetPackageName (), R.layout.clock_widget_layout);Hiervoor hebt u nog een importverklaring nodig:
import android.widget.RemoteViews;Vergeet niet dat we elk Analog Clock-ontwerp hebben opgenomen in het widgetlay-outbestand. Dit komt omdat we de kenmerken van een analoge klok, zoals de tekstrappen voor de draaiknop en wijzers, niet dynamisch kunnen wijzigen, dus we nemen in plaats daarvan alle ontwerpen op en stellen alles in maar een om onzichtbaar te zijn. Voordat we het gekozen klokontwerp zichtbaar maken, stellen we de andere in als onzichtbaar, wat we als volgt in een lus kunnen doen:
voor (int d = 0; dWe gebruiken de array waarin we de Analog Clock-element-ID-waarden hebben opgeslagen om ze allemaal onzichtbaar te maken, zolang deze niet de gekozen is. Nu kunnen we het gekozen ontwerp zichtbaar maken, na deze lus:
remoteViews.setViewVisibility (pickedClock, View.VISIBLE);Omdat dit een widget-app is, moeten we het uiterlijk van de widget als volgt bijwerken:
// componentnaam ophalen voor widgetklasse ComponentName comp = new ComponentName (this, ClockWidget.class); // AppWidgetManager AppWidgetManager-app ophalenWidgetManager = AppWidgetManager.getInstance (this.getApplicationContext ()); // update appWidgetManager.updateAppWidget (comp, remoteViews);Dit is vergelijkbaar met de manier waarop we de widget hebben bijgewerkt in de widgetproviderklasse, maar met een aantal extra verwerkingsstappen omdat we hier in een klasse Activity zitten. U moet deze importen toevoegen:
importeer android.appwidget.AppWidgetManager; importeer android.content.ComponentName;Het uiterlijk van de widget wordt nu bijgewerkt volgens de keuze van de gebruiker.
Stap 5: Gedeelde voorkeuren bijwerken
Vervolgens gaan we de toepassing Gedeelde voorkeuren gebruiken om de ontwerpkeuze voor de gebruiker op te slaan. Maak een back-up van de activiteitsklasse bovenaan de klokkeuze en voeg een andere instantievariabele toe:
private SharedPreferences clockPrefs;Nu aan het einde van de methode "onCreate" voegt u na de bestaande code het volgende toe om de variabele Shared Preferences te instantiëren:
clockPrefs = getSharedPreferences ("CustomClockPrefs", 0);We zullen dezelfde voorkeurennaam gebruiken elke keer dat we toegang krijgen tot de gegevens met betrekking tot de keuze van de gebruiker. Ga nu naar het einde van de "onClick" -methode, na de code waarin we de widget hebben bijgewerkt. Download de voorkeureneditor als volgt:
SharedPreferences.Editor custClockEdit = clockPrefs.edit ();Geef nu de gegevens met betrekking tot de gebruikerskeuze door aan de editor en verbind deze:
custClockEdit.putInt ("clockdesign", gepickt); custClockEdit.commit ();We specificeren een naam voor de gegevenswaarde en de ID van het gekozen ontwerp. Tot slot, voeg nog steeds bij "onClick" het volgende toe terwijl de taak van de activiteit is voltooid:
af hebben();
Stap 6: Controleer gedeelde voorkeuren
Nu kunnen we vanuit de widgetklasse gebruikmaken van de gegevens voor gedeelde voorkeuren. Open uw "ClockWidget" -klasse, die AppWidgetProvider uitbreidt. De algoritmen die we hier gebruiken, zijn vergelijkbaar met de algoritmen die we hierboven hebben gebruikt voor het beheer van de klokontwerpen. Voeg de volgende aanvullende instantievariabelen bovenaan toe:
// preferences private SharedPreferences custClockPrefs; // aantal mogelijke ontwerpen private intNoClocks; // ID's van analoge klokelementen int [] klokontwerpen;U heeft de volgende import nodig:
importeer android.content.SharedPreferences;In de "onReceive" -methode, voor de bestaande code, haal het aantal ontwerpen terug uit onze waardegrondstof:
numClocks = context.getResources (). getInteger (R.integer.num_clocks);Start de array met klok-ID's als volgt:
clockDesigns = new int [numClocks];Doorloop nu deze array en stel elk element in als ID voor het relevante Analoge klokelement in de widgetlay-out:
voor (int d = 0; dGa nu naar de inhoud van de "als" -instructie in de "onReceive" -methode, na de regel waarin we de Remote Views-weergaven hebben opgehaald en vóór de regel waarin we de Intentie voor de klokkeuzeklasse hebben gemaakt, de Gemeenschappelijke voorkeuren en controleer voor de gegevenswaarde die we instellen voor de keuze van de gebruiker:
custClockPrefs = context.getSharedPreferences ("CustomClockPrefs", 0); int chosenDesign = custClockPrefs.getInt ("clockdesign", -1);De naam van de gedeelde voorkeuren en de gegevenswaarde moeten overeenkomen met wat u hebt opgenomen bij het instellen van de keuze van de gebruiker in de bovenstaande chooseractiviteit. De gebruiker heeft mogelijk nog geen ontwerp gekozen, dus neem een "als" -instructie op om te controleren:
if (selectedDesign> = 0)In de "if" -instructie moet je eerst de ontwerpen doorlopen en elk onzichtbaar instellen als het niet het gekozen patroon is:
voor (int d = 0; dU heeft nog een import nodig:
import android.view.View;Stel nu het gekozen ontwerp zichtbaar in:
views.setViewVisibility (clockDesigns [selectedDesign], View.VISIBLE);Wanneer de widget nu is bijgewerkt en de gebruiker een ontwerp heeft gekozen, wordt dat ontwerp weergegeven.
Conclusie
Dat is de voltooide klok widget! U kunt het uitvoeren op een emulator of apparaat om het te testen. Het moet continu werken, de tijd bijwerken en de ontwerpkeuze van de gebruiker weergeven.
Neem even de tijd om terug te blikken op de verschillende applicatie-elementen en zorg ervoor dat u begrijpt hoe ze in combinatie met elkaar werken. Bij het ontwikkelen van een andere widget-app worden veel dezelfde stappen uitgevoerd. De vitale elementen in een widget-app zijn: het XML "appwidget-provider" element, het Manifest-bestand, de klasse die AppWidgetProvider uitbreidt en natuurlijk de visuele elementen inclusief lay-outs en bronnen.
Als je de vaardigheden die je in deze serie hebt geleerd verder wilt ontwikkelen, zijn er een aantal opties. Als u een geavanceerde gebruikersconfiguratie voor uw widgets wilt bieden, kunt u een voorkeursactiviteit gebruiken in combinatie met de APPWIDGET_CONFIGURE actie. Als u digitale klokdisplays samen met uw analoge opties wilt opnemen, is het proces een beetje ingewikkelder. U kunt de standaard digitale klokklasse opnemen in een standaardapp, maar niet in een widget-app, dus u moet de digitale tijdweergave implementeren en uzelf bijwerken met behulp van extra componenten zoals services en alarmbeheerders..
U kunt de volledige broncode en afbeeldingen gebruiken voor deze zelfstudie op de downloadlink.