Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Sat, 07 Mar 2009 10:53:20 GMT


Sponsored Links
  have a list activity that creates a header row above the data rows
from the adapter. I want to receive click events when the user selects
the header or a data row (but my data rows have check boxes in them,
so this part is tricky). When I use the touch screen, I get this
expected behavior:

1. Tapping on any row causes a click event and a dialog appears.
2. Long-pressing on a data row causes a context menu to appear.
3. Long-pressing on the header row does *not* show the context menu.

However, when I use the arrow keys (emulator) or trackball (G1), I get
this unexpected behavior:

1. Selecting any row fails to cause any click events, even though the
row's appearance changes like it's being clicked.
2. Long-pressing on the header row *does* show the context menu, which
I don't want.
3. Occasionally, it doesn't focus the correct row when I move up or
down (e.g. it skips from the header to the last data row).

What am I doing wrong?

Jesse

(Complete project: http://hansprestige.com/android/DpadBug.zip)

////////// DpadActivity.java //////////

package com.hansprestige.DpadBug;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class DpadBugActivity extends ListActivity {
private static final int DIALOG_TEST = 1;

private OnClickListener testListener = new OnClickListener() {
public void onClick(View v) {
showDialog(DIALOG_TEST);
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ListView lv = getListView();
registerForContextMenu(lv);

findViewById(android.R.id.empty).setOnClickListener
(testListener);

View addItem = getLayoutInflater().inflate
(R.layout.list_header,
null, false);
addItem.setOnClickListener(testListener);
lv.addHeaderView(addItem);

fillData();
}

private void fillData()
{
String[] items = new String[] { "Item A", "Item B", "Item C" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.list_row, R.id.TextView01, items) {
@Override
public View getView(int position, View convertView, ViewGroup
parent) {
View v = super.getView(position, convertView, parent);
v.setOnClickListener(testListener);
v.setLongClickable(true);
return v;
}
};
setListAdapter(adapter);
}

@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_TEST:
return new AlertDialog.Builder(this)
.setTitle("Hello!")
.setPositiveButton("Close", null)
.create();
}
return super.onCreateDialog(id);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
Context



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Wed, 11 Mar 2009 08:31:10 GMT


 nybody?

On Mar 5, 6:54pm, Jesse McGrew <jmcg...@gmail.com> wrote:
--~--~---------~--~----~------------~-------~--~----~


Sponsored Links


Trackball doesn't give me click events, but touch screen does

by Streets Of Boston » Wed, 11 Mar 2009 12:17:51 GMT


 'm not sure, but try this:
Add a key-event listener to your item instead of the onClick:
...
...
v.setOnKeyListener(myKeyListener);
...

And in that listener, handle the key-codes KeyEvent.KEYCODE_DPAD_x
where x = CENTER, DOWN, UP, LEFT or RIGHT.


On Mar 10, 8:30pm, Jesse McGrew <jmcg...@gmail.com> wrote:
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Romain Guy (Google) » Thu, 12 Mar 2009 07:39:03 GMT


 i Jesse,

You should **not** set individual click listeners on the list items.
This will cause all sort of problems, like the ones you're seeing. The
main reason behind that is that ListView handles clicks/long clicks on
the items already. Instead you should use
ListView.setOnItemClickListener().

On Mar 5, 6:54pm, Jesse McGrew <jmcg...@gmail.com> wrote:
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Thu, 12 Mar 2009 08:57:48 GMT


 omain,

Thanks for your response. I'm not sure if that approach will work,
though. My ListActivity's onListItemClick() method is called when I
click on an item with the trackball, but *not* when I touch it.

Perhaps the root problem is that my list rows have focusable items in
them (check boxes). The built-in Alarm Clock application has something
similar, though, and I can see from the source code that Alarm Clock
sets individual click listeners on the check boxes and the clock
views.

I'm trying to get the same behavior as Alarm Clock, where tapping on a
list row brings up an activity to edit the row, and the check box can
only be selected by tapping on the check box itself. I think that
precludes using multiple-choice mode for the list view, correct?

Jesse

On Mar 11, 4:38pm, "Romain Guy (Google)" <romain...@google.com>
wrote:
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Thu, 12 Mar 2009 09:07:26 GMT


 


It looks like I can handle both cases by setting a click listener on
the row *and* responding to onListItemClick().

Now I wonder if there's a way to make the context menu only appear for
data rows, not the list header row. (This works as expected with
touch, but with the trackball, I still get a context menu on the
header row.)

Jesse
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Thu, 12 Mar 2009 09:28:57 GMT


 


Interesting. Unfortunately I can't find any examples of TouchDelegate,
and the class documentation is confusing.

I gather that I need to pass the bounds of the check box (relative to
its container) into the TouchDelegate constructor. Once I have a
TouchDelegate instance, what do I do with it? I see a method called
setTouchDelegate() - do I call that on the check box, the list row, or
the view group that directly contains the check box? And is that
method enough to get the touch events relayed to the delegate, or do I
need to listen for touch events and forward them myself?

Jesse
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Thu, 12 Mar 2009 10:01:31 GMT


 




Also: would it still be possible to focus the check box using the
trackball? I assumed TouchDelegates were only for touch, and so the
trackball would only be able to move between list rows. In AlarmClock,
the trackball can move horizontally between the clock view and check
box inside a row, as well as moving vertically between rows.

Jesse
--~--~---------~--~----~------------~-------~--~----~



Trackball doesn't give me click events, but touch screen does

by Jesse McGrew » Thu, 12 Mar 2009 11:07:36 GMT


 Aha! Adding a call to that method fixes both the context menu problem
and the click handler problem. Thanks.

Jesse







--~--~---------~--~----~------------~-------~--~----~



Other Threads

1. Animation of a View

I understand that animating a View using startAnimation() with a
TranslateAnimation object really just applies a transform on the
canvas that is being drawn on. In my case, the problems with this are:
a) sometimes I need to call bringChildToFront() (for a different View)
on the ViewGroup during the animation, which messes up the animation
because it triggers a requestLayout on all children, which in turn re-
lays out the child being animated... which messes up the continuity of
the animation. Perhaps causing a layout on the child being animated
isn't supposed to mess up animations, but it seems to be in my case.
b) after the animation (using an AnimationListener), I need to re-
layout the child to the new location, which is fine in concept, but
again messes up the animation because for some reason the actual
drawing of the last frame of the animation hasn't finished by the time
onAnimationEnd() is called. This causes the animation to go awry at
the very end. What's happening in my case is if I layout the animated
view to its new location in onAnimationEnd, the last step of the
animation is being applied to the new layout, so the view looks like
it is jumping around the screen. I tried a handler with no delay, and
that didn't work either. Using a handler with a delayed message to
accomplish the new layout works but is such a hack that I worry it may
not work correctly on another piece of hardware.

I could accomplish the animation by taking out the TranslateAnimation
and instead do a manual animation, and in the manual one, change the
layout of the view gradually (instead of transforming the matrix of
the canvas) but that's a lot of work and error-prone.

Any ideas? Are there tools I can use (besides manual application of
Handler.sendMessageDelayed()) to accomplish an animation that actually
re-lays out the view on each iteration instead of altering the canvas
matrix?
--~--~---------~--~----~------------~-------~--~----~

2. Mediastore thumbnail refresh

I use the image_capture intent to take a picture. But when I
subsequently access the gallery from within my app, the picture
doesn't show up. Apparently the thumbnails aren't refreshed in the
mean time? How can I force a refresh of the gallery thumbnails? I
couldn't find a method to do so - though I may have overlooked it.

--~--~---------~--~----~------------~-------~--~----~

3. Best practices for handling passwords/keys in open source projects?

4. any update on ADC 2?

5. can't bind to a local service.

6. Know when Outgoing Call has been answered or whatever state

7. MyTouch Lag Problems