Alright, I have made the appropriate changes to my SeqSwitch class so that I no longer call setBackgroundResource from my onDraw (and in fact no longer override onDraw at all). Now, Mark, I have written an audio pattern playback implementation using a Handler that runs in my main Activity and, while it works, it is way less smooth and reliable than the implementation using the Timer/separate thread. I tried to wade through the docs for AsyncTask and I could not tell whether or not it would allow me to update the UI from my separate Timer thread. Will it, or do I just have to choose between having smooth audio playback in a separate thread but no visual feedback and having less reliable audio playback in my UI thread with visual feedback? Thanks again, Nick Zaillian
On Aug 30, 4:13 pm, Romain Guy <[email protected]> wrote: > You should call setBackgroundResource() but NOT from onDraw(). Just > call this method from setIlluminated() for instance. > > > > On Sun, Aug 30, 2009 at 1:06 PM, Nick_Zaillian<[email protected]> wrote: > > > Mark and Romain, > > Thanks. That was a much prompter response than I either expected or > > deserved. > > Romain, I am not sure that I totally understand what you've said. How > > am I to set the background in accordance with the state of isChecked > > and isIlluminated from within onDraw if not by calling > > setBackgroundResource()? I guess this post probably belongs in the > > Android Beginner's group. > > Thanks, > > Nick Zaillian > > > On Aug 30, 2:59 pm, Romain Guy <[email protected]> wrote: > >> Do not call setBacgroundResource() in onDraw()! You are loading and > >> setting an image every time your view is drawn. You are actually > >> creating a infinite "loop"; > > >> onDraw() -> setBacgroundResource() -> invalidate() -> onDraw() -> > >> setBacgroundResource() -> etc. > > >> On Sun, Aug 30, 2009 at 11:47 AM, Nick_Zaillian<[email protected]> wrote: > > >> > Hey all, > >> > I am writing an app that emulates a drum machine with a step > >> > sequencer. For those unfamiliar with step sequencers, a step > >> > sequencer is basically a set of switches where the state of each > >> > switch indicates whether or not a sound is to be played at a > >> > particular point in a pattern. I've already got audio playback > >> > working using SoundPool and can play patterns (represented as objects > >> > containing boolean arrays mapped to audio resources) by stepping > >> > through these patterns using a timer. What I am trying and struggling > >> > to do at present is to write my UI. I have subclassed ToggleSwitch > >> > and made a custom switch called SeqSwitch which, in addition to > >> > ToggleSwitch's isChecked field, also holds an isIlluminated field. > >> > I've written another class called SwitchController that takes an array > >> > of these switches and has a method (which I've called runSwitches) > >> > that, with each call, advances one switch, illuminates the current > >> > switch, and unilluminates the previous switch (the idea is that, when > >> > the user plays his pattern, the button representing the current step > >> > will illuminate, letting him know the current position of playback in > >> > the sequence). The SeqSwitches seem to render and behave fine in > >> > response to clicks. My SwitchController.runSwitches method also works > >> > so long as I place it in a click handler of a button in my main > >> > Activity. When, however, I pass it into the runnable (called > >> > PatternPlayTask) that I give to my Timer (which then calls > >> > SwitchController.runSwitches every 300 milliseconds as it steps > >> > through the pattern), it stops working. I have used the debugger to > >> > make sure that the object I am passing into the runnable is the same > >> > as the one for which the call to SwitchController.runSwitches was > >> > working in the main activity and have found that definitely it is. > >> > Does anybody have any idea what's going on here. Hopefully I am just > >> > doing something totally stupid, here. I've pasted the code for my > >> > ToggleButton subclass below, if that helps: > > >> > package com.drummachine; > >> > import android.widget.*; > >> > import android.view.*; > >> > import android.content.Context; > >> > import com.drummachine.Instrument; > >> > import android.util.*; > >> > import android.content.res.TypedArray; > >> > import android.graphics.Canvas; > >> > import android.graphics.Paint; > >> > import android.graphics.drawable.*; > >> > import android.util.AttributeSet; > >> > import android.view.View; > > >> > public class SeqSwitch extends ToggleButton { > > >> > //SeqSwitch holds an isIlluminated state. > >> > //if isIlluminated is true, onDraw will render an illuminated > >> > //button image as the SeqSwitch's drawable (currently the same > >> > image > >> > used for > >> > //a ToggleButton whose isChecked == true) > >> > public boolean isIlluminated; > > >> > public SeqSwitch(Context context) > >> > { > >> > super(context); > >> > isIlluminated = false; > > >> > } > > >> > //constructor called when params are taken from XML layout > >> > public SeqSwitch(Context context, AttributeSet attributes) { > >> > super(context, attributes); > > >> > TypedArray a = context.obtainStyledAttributes(attributes, > >> > R.styleable.SeqSwitch); > > >> > isIlluminated = false; > >> > super.setBackgroundResource > >> > (R.drawable.seqswitchbackgroundsoneoff); > > >> > a.recycle(); > >> > } > > >> > public void setIlluminated(boolean state) > >> > { > >> > isIlluminated = state; > >> > this.invalidate(); > > >> > } > > >> > //yes, I know having illumniate() and unIlluminate() methods is > >> > redundant > >> > //when I have a setIlluminated(boolean) method, but I am presently > >> > too lazy > >> > //to rearrange code elsewhere that presently relies on these two > >> > methods. > >> > public void unIlluminate() > >> > { > >> > isIlluminated = false; > >> > this.invalidate(); > >> > } > > >> > public void illuminate() > >> > { > >> > isIlluminated = true; > >> > this.invalidate(); > >> > } > > >> > public boolean switchIsIlluminated() > >> > { > >> > return isIlluminated; > >> > } > > >> > /** > >> > * renders a image of a switch with an illuminated LED if either > >> > the SeqSwitch's isChecked or > >> > * isIllumniated == true. Otherwise it renders a drawable of a > >> > button with an unIlluminated LED > >> > */ > >> > public void onDraw(Canvas canvas) > >> > { > >> > if(super.isChecked() == true || this.isIlluminated == true) > >> > { > >> > super.setBackgroundResource > >> > (R.drawable.seqswitchbackgroundsoneonon); > >> > } > >> > else > >> > { > >> > super.setBackgroundResource > >> > (R.drawable.seqswitchbackgroundsoneoff); > >> > } > > >> > } > >> > } > > >> > Thanks, > >> > Nick Zaillian > > >> -- > >> Romain Guy > >> Android framework engineer > >> [email protected] > > >> Note: please don't send private questions to me, as I don't have time > >> to provide private support. All such questions should be posted on > >> public forums, where I and others can see and answer them > > -- > Romain Guy > Android framework engineer > [email protected] > > Note: please don't send private questions to me, as I don't have time > to provide private support. All such questions should be posted on > public forums, where I and others can see and answer them --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en -~----------~----~----~----~------~----~------~--~---

