2

我有一个列表视图,其项目是由 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,那就是:背景在 250 毫秒内从白色变为青色,之后它会触发 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 事件来一次制作应用程序的逻辑?

我怎样才能恢复并定制化“按下按钮”的反馈?

编辑发布代码:

嗯,有要求的代码。

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;
}
}
4

2 回答 2

1

我认为您需要更改 onTouch() 方法

@Override
public boolean onTouch(View v, MotionEvent event) {
    int eventaction = event.getAction();
    switch (eventaction) {
        case MotionEvent.ACTION_DOWN: 
        transition.startTransition(duration);
        //Tell Android that you can handle this MotionEvent, and you 
        //want to keep informed of further events of this touch
        return true;
        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;
}

希望能帮助到你。

于 2013-08-25T02:18:27.957 回答
0
public boolean onTouch(MotionEvent ev) {
 ...
 return super.onTouch(ev);
}

也许你不应该自己返回 false 。

于 2014-12-25T07:48:50.877 回答