【发布时间】:2013-06-29 20:25:50
【问题描述】:
我有一个列表视图,其项目是由 2 个标签和一个相对布局中的按钮组成的自定义视图。
执行此操作时,单击列表视图按钮的“反馈” - 当您触摸它时项目更改了背景颜色 - 消失了,所以我决定使用 ACTION_DOWN 和 ACTION_UP 来完成它
我做了这门课来放入所有具有相同问题的列表视图:
// The same instance of this class is setted as onTouchListener to the labels and the layout
public class OnTouchChangeColor implements OnTouchListener {
TransitionDrawable transition;
private final int duration = 250;
public static final int INITCOLOR = Color.WHITE;
public static final int FINALCOLOR = Color.CYAN;
// this will be the layout container of the labels and the button
ViewGroup layout = null;
public OnTouchChangeColor(ViewGroup layout){
update(layout);
}
public void update(ViewGroup layout){
this.layout = layout;
TransitionDrawable t = new TransitionDrawable(new Drawable[]{new ColorDrawable(INITCOLOR), new ColorDrawable(FINALCOLOR)});
layout.setBackgroundDrawable(t);
transition = (TransitionDrawable) layout.getBackground();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
transition.startTransition(duration);
break;
case MotionEvent.ACTION_UP:
transition.reverseTransition(duration);
break;
}
// tell the system that we handled the event but a further processing is required
return false;
}
问题是项目获得了触摸事件ACTION_DOWN而不是ACTION_UP,那就是:背景在250ms内从白色变为青色,之后它会触发onclick事件,但不会触发ACTION_UP...
onClick 这样做:
@Override
public void onClick(View v) {
try {
loadData();
} catch (IOException e) {
e.printStackTrace();
}
Intent intent = new Intent(context, ActDestiny.class);
intent.putExtra("stop", true);
context.startActivity(intent);
}
嗯:它进入下一个活动,但它没有将其背景恢复为白色......不仅如此:有时它没有进入它的命运,但背景变为青色并卡在青色中。 ..
我在 android 文档中读到在 ontouch 函数中返回“false”:
所以,如果在接收到 down 操作事件时返回 false,则表明您没有消费该事件,并且对该事件的后续操作也不感兴趣。因此,您不会被要求执行事件中的任何其他操作,例如手指手势或最终的向上操作事件。
因此,如果我返回 true,则反馈有效,但事件已被消耗,并且 onclick 不起作用...
所以我不知道该怎么做才能获得触摸项目的“反馈”和 onclick 事件的工作......
我可以在 ACTION_UP 中调用 onClick,但它非常丑陋 - 特别是在 'onLongClick' 事件中思考-。
可以用ACTION_DOWN、ACTION_UP制作动画,用onClick事件一次性制作app的逻辑吗?
如何恢复 - 并定制化 - “按下按钮”的反馈?
编辑发布代码:
嗯,有请求的代码。
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_titular_mp3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/LblTitulo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/btnAccion"
android:textSize="20dp"
android:textStyle="bold" />
<TextView
android:id="@+id/LblSubTitulo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/LblTitulo"
android:layout_toLeftOf="@id/btnAccion"
android:text=" "
android:textSize="12dp"
android:textStyle="normal" />
<Button
android:id="@+id/btnAccion"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="@drawable/playbutton_style"
android:gravity="center_vertical|center_horizontal|right"
android:visibility="gone" />
</RelativeLayout>
还有适配器的代码。请注意,当我这样做时:
cvh.updateCustomOnClickBases(titActual, context,posicion);
cvh.updateOnTouchListeners();
我这样做是因为 listView 仅创建屏幕上的视图,并且当您向下滚动时,它会记录退出的视图(上面的视图)以及数据数组中下一项的信息(这将是如下所示)。
所以我也记录了事件监听器,更新了他们的引用。代码如下。
public class AdaptPlayList extends BaseAdapter {
private final Context context;
ArrayList<PlayList> datos;
long id;
public AdaptPlayList(Context context, ArrayList<PlayList> datos, int typ) {
this.datos = datos;
this.context = context;
}
public void updatePlaylist(ArrayList<PlayList> pl){
ThreadPreconditions.checkOnMainThread();
this.datos = pl;
notifyDataSetChanged();
}
@Override
public int getCount(){
return datos.size();
}
@Override
public PlayList getItem(int index) {
return datos.get(index);
}
@Override
public long getItemId(int index) {
return index;
}
public View getView(int posicion, View convertView, ViewGroup parent) {
final PlayList titActual = getItem(posicion);
CancionViewHolder cvh;
if (convertView == null) {
cvh = new CancionViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.titularmp3, parent, false);
OnPlaylistItemClick itemClick = new OnPlaylistItemClick(titActual, context,posicion);
cvh.titulo = (TextView) convertView.findViewById(R.id.LblTitulo);
cvh.btnAction = (Button) convertView.findViewById(R.id.btnAccion);
cvh.layout = (ViewGroup)convertView.findViewById(R.id.layout_titular_mp3);
cvh.click = itemClick;
cvh.longClick = itemClick;
cvh.btnClick = new OnPlaylistButtonClick(titActual, context,posicion);
convertView.setTag(cvh);
}else{
cvh = (CancionViewHolder)convertView.getTag();
}
cvh.updateCustomOnClickBases(titActual, context,posicion);
cvh.updateOnTouchListeners();
TextView titulo = cvh.titulo;
Button btnAction = cvh.btnAction;
titulo.setText(titActual.getDesc());
btnAction.setVisibility(View.VISIBLE);
btnAction.setOnClickListener(cvh.btnClick);
titulo.setOnClickListener(cvh.click);
titulo.setOnLongClickListener(cvh.longClick);
return convertView;
}
}
class OnPlaylistItemClick extends CustomOnClickBase implements OnClickListener, OnLongClickListener{
public OnPlaylistItemClick(PlayList pl, Context ctx, int position) {
super(pl, ctx, position);
}
@Override
public boolean onLongClick(View v) {
// do things....
//
Intent intent = new Intent(context, ActListadoCancionesAsync.class);
intent.putExtra("stopMusic", true);
context.startActivity(intent);
return true;
}
@Override
public void onClick(View v) {
// do more things!
}
}
}
class OnPlaylistButtonClick extends CustomOnClickBase implements OnClickListener{
PlayList titActual;
public OnPlaylistButtonClick(PlayList pl, Context ctx, int position) {
super(pl, ctx, position);
titActual = pl;
}
@Override
public void onClick(View v) {
// do things
//....
Intent intent = new Intent(context, ActListadoCancionesAsync.class);
intent.putExtra("stopMusic", true);
context.startActivity(intent);
}
}
有了这个持有者和clickbase,我避免了对象的创建(我构建了一个更新列表视图项目的事件监听器,而不是创建新的监听器)
public class CancionViewHolder{
public TextView titulo;
public TextView subtitulo;
public ToggleButton button;
public Button btnAction;
public OnClickListener btnClick;
public OnClickListener click;
public OnLongClickListener longClick;
public ViewGroup layout = null;
/**Actualiza los eventos que estan cacheados para que apunten a sus nuevos contenidos del adapter. De otro modo, como los
* datos del adapter se moveran mientras que los views seran reutilizados los eventos apuntarian a la anterior posicion
* @param datosItem
* @param ctx
* @param pos
*/
public void updateCustomOnClickBases(Object datosItem, Context ctx, int pos){
((CustomOnClickBase)click).updateObject(datosItem, ctx,pos, layout);
((CustomOnClickBase)longClick).updateObject(datosItem, ctx,pos, layout);
((CustomOnClickBase)btnClick).updateObject(datosItem, ctx,pos, layout);
}
/**
* Establece los listeners que hacen efectos cuando se pulsa algo
*/
public void updateOnTouchListeners() {
if (layout != null) {
OnTouchChangeColor cc = new OnTouchChangeColor(layout);
layout.setOnTouchListener(cc);
if (subtitulo != null){
subtitulo.setOnTouchListener(cc);
}
if (titulo != null){
titulo.setOnTouchListener(cc);
}
}
}
}
和
public abstract class CustomOnClickBase {
protected Object datosItem;
protected Context context;
protected int position;
protected ViewGroup layout;
public CustomOnClickBase(Object datosItem, Context ctx, int position){
updateObject(datosItem, ctx, position, layout);
}
public void updateObject(Object datosItem, Context ctx, int position, ViewGroup layout){
this.datosItem = datosItem;
context =ctx;
this.position = position;
this.layout = layout;
}
}
【问题讨论】:
-
您的列表项布局或您通过适配器设置视图的方式可能有问题。列表项的触摸反馈应该与任何其他布局没有什么不同。您可以发布您的列表项 XML 和您的适配器代码吗?
-
我发布了代码...您一定是正确的...我记得当我将事件处理从活动(通过 listView.setOnItemClickListener... 等)移动到适配器时,反馈消失了通过 view.setOnClickListeners... 等
标签: android