android - 如何使用按钮实现自定义 ListView 行?

标签 android listview event-handling

我有一个 ExpandableListView我想用 NoteView 类型的自定义 View 填充。 NoteView 扩展了 LinearLayout 并包含两个按钮和一个复选框。我几乎所有的东西都在工作,NoteView 正在填充支持数据,列表正在填充,按钮是可点击的并执行所需的任务。

问题是 ExpandableListView不再响应点击/长按/按键事件(除了使用轨迹球/DPAD 选择列表项)。

我用标准 TextView 替换了我的自定义 View ,并且触摸事件再次正常流动,所以几乎可以肯定是我的自定义 View 做错了,或者我忽略了一些晦涩的 ListView 设置。

这是我的 NoteView 代码和 XML 布局。我错过了什么?

//Custom Note View
public class NoteView extends LinearLayout{

    private CheckBox mCheckBox;
    private TextView mTitleTextView;
    private TextView mDetailsTextView;
    private TextView mDetailsRightTextView;
    private LinearLayout mButtonLayout;
    private Button mDeleteButton;
    private Button mEditButton;

    //data storage
    private long mNoteId = -1;
    private boolean mStretched = false;
    private CharSequence mDetails = "";
    private CharSequence mStretchedDetails = "";
    private CharSequence mDetailsRight = "";
    private CharSequence mStretchedDetailsRight = "";       


    private NoteView.OnNoteButtonClickedListener mEditNoteListener;
    private NoteView.OnNoteButtonClickedListener mDeleteNoteListener;
    private NoteView.OnNoteCheckBoxClickedListener mCheckboxListener;

    public NoteView(Context context) {
        super(context);
        init(context);
    }

    public NoteView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }


    private void init(Context context) {

        this.setPadding(0, 0, 5, 0);
        this.setOrientation(LinearLayout.VERTICAL);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.noteview_layout, this);//returns the noteview itself, since is parent

        //get views
        mCheckBox = (CheckBox) findViewById(R.id.noteViewCB);
        mTitleTextView = (TextView) findViewById(R.id.noteViewTitle);
        mDetailsRightTextView = (TextView) findViewById(R.id.noteViewDetailsRight);
        mDetailsTextView =  (TextView) findViewById(R.id.noteViewDetails);


        mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(mCheckboxListener != null)
                {
                    mCheckboxListener.onNoteCheckBoxClicked(mNoteId, isChecked);
                }
            }
        });

        //prepare button layout
        mButtonLayout = (LinearLayout) findViewById(R.id.noteViewButtonLayout);
        mEditButton = (Button) findViewById(R.id.noteViewEditButton);
        mDeleteButton = (Button) findViewById(R.id.noteViewDeleteButton);


        mEditButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if(mEditNoteListener != null)
                {
                    mEditNoteListener.onNoteButtonClicked(mNoteId);
                }
            }
        });

        mDeleteButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if(mDeleteNoteListener != null)
                {
                    mDeleteNoteListener.onNoteButtonClicked(mNoteId);
                }
            }
        });

    }

    public void setOnEditClickedListener(NoteView.OnNoteButtonClickedListener listener)
    {
        mEditNoteListener = listener;
    }

    public void setOnDeleteClickedListener(NoteView.OnNoteButtonClickedListener listener)
    {
        mDeleteNoteListener = listener;
    }


    public void setOnCheckboxClickedListener(NoteView.OnNoteCheckBoxClickedListener listener)
    {
        mCheckboxListener = listener;
    }

    static abstract class OnNoteButtonClickedListener
    {
        public abstract void onNoteButtonClicked(long noteId);
    }


    static abstract class OnNoteCheckBoxClickedListener
    {
        public abstract void onNoteCheckBoxClicked(long noteId, boolean checked);
    }


    public void setNoteId(long noteId)
    {
        mNoteId = noteId;   
    }

    public long getNoteId()
    {
        return mNoteId;
    }

    public void setTitle(CharSequence title)
    {
        mTitleTextView.setText(title);
    }

    public void setChecked(boolean checked)
    {
        mCheckBox.setChecked(checked);
    }

    public boolean isChecked()
    {
        return mCheckBox.isChecked();
    }

    public void setDetails(CharSequence details, CharSequence stretchedDetails)
    {
        if(details == null || details.length() == 0)
        {
            mDetails = "";
        }else
        {
            mDetails = details;
        }

        if(stretchedDetails == null)
        {
            mStretchedDetails = "";
        }
        else
        {
            mStretchedDetails = stretchedDetails;
        }

        refreshStretched();
    }

    public void setDetailsRight(CharSequence detailsRight, CharSequence expandedDetailsRight)
    {
        if(detailsRight == null || detailsRight.length() == 0)
        {
            mDetailsRight = "";
        }else
        {
            mDetailsRight = detailsRight;
        }

        if(expandedDetailsRight == null)
        {
            mStretchedDetailsRight = "";
        }
        else
        {
            mStretchedDetailsRight = expandedDetailsRight;
        }

        refreshStretched();
    }

    public void setStretched(boolean expanded)
    {
        mStretched = expanded;
        refreshStretched();
    }

    public boolean getStretched()
    {
        return mStretched;
    }

    public boolean toggleStretched()
    {
        setStretched(!getStretched());
        return mStretched;
    }

    public void showButtons() {

        if(mButtonLayout.getVisibility() != VISIBLE )
        {
            Animation slideIn = AnimationUtils.loadAnimation(this.getContext(), R.anim.slideonfromright);

            mButtonLayout.setAnimation(slideIn);
            mButtonLayout.setVisibility(VISIBLE);
            mButtonLayout.startAnimation(slideIn);
        }       
    }

    public void hideButtons() {
        if(mButtonLayout != null && mButtonLayout.getVisibility() == VISIBLE )
        {
            Animation slideOut = AnimationUtils.loadAnimation(this.getContext(), R.anim.slideofftoright);
            slideOut.setAnimationListener(new AnimationListener()
            {
                @Override
                public void onAnimationEnd(Animation animation) {
                    mButtonLayout.setVisibility(GONE);
                }
                @Override
                public void onAnimationRepeat(Animation animation) {}
                @Override
                public void onAnimationStart(Animation animation) { }
            });

            mButtonLayout.startAnimation(slideOut);
        }
    }


    public void hideButtons(boolean noAnimation) {
        mButtonLayout.setVisibility(GONE);
    }

    public void refreshStretched() {

        if(mStretched)
        {
            mDetailsRightTextView.setText(mStretchedDetailsRight);
            mDetailsTextView.setText(mStretchedDetails);
        }else
        {
            mDetailsRightTextView.setText(mDetailsRight);
            mDetailsTextView.setText(mDetails);
        }

        if(mDetailsRightTextView.length() == 0)
        {

            mDetailsRightTextView.setVisibility(GONE);
        }else
        {
            mDetailsRightTextView.setVisibility(VISIBLE);
        }

        if(mDetailsTextView.length() == 0)
        {
            mDetailsTextView.setVisibility(GONE);
        }else
        {
            mDetailsTextView.setVisibility(VISIBLE);
        }
    }
}

noteview_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:paddingRight="5dip">
        <CheckBox android:id="@+id/noteViewCB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
        <TextView android:id="@+id/noteViewTitle"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="Title"/>
        <LinearLayout
                android:id="@+id/noteViewButtonLayout"
                android:orientation="horizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dip"
                android:visibility="gone"
                android:layout_gravity="center_vertical">
            <Button android:id="@+id/noteViewEditButton"
                    android:layout_width="80dp"
                    android:layout_height="fill_parent"
                    android:background="@drawable/drawngreenbutton"
                    android:textStyle="bold"
                    android:text="Edit"/>
            <Button android:id="@+id/noteViewDeleteButton"
                    android:layout_width="80dp"
                    android:layout_height="fill_parent"
                    android:background="@drawable/drawnredbutton"
                    android:textStyle="bold"
                    android:text="Delete"/>
        </LinearLayout>
    </LinearLayout>
    <LinearLayout  android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <TextView android:id="@+id/noteViewDetails"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="2"
    android:layout_marginRight="10dip"
    android:visibility="gone"
    android:focusable="false"
    android:bufferType="spannable"/>
    <TextView 
    android:id="@+id/noteViewDetailsRight"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:visibility="gone"
    android:focusable="false"
    android:bufferType="spannable"
    android:gravity="right"/></LinearLayout>
</merge>

最佳答案

当在 ListView 项目布局中使用复选框时,我遇到了类似的问题。 请检查是否添加属性: 机器人:可聚焦=“假” 复选框定义可以帮助您喜欢:

<CheckBox android:id="@+id/noteViewCB" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:focusable="false" />

问题似乎是 Android 不允许您选择具有可聚焦元素的列表项。

最好的,

关于android - 如何使用按钮实现自定义 ListView 行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3892006/

相关文章:

java - 如何在将图像上传到 Firebase 之前调整图像大小?

android - GlSurfaceView setZMediaOrder 导致视频在其 parent 之外播放

java - 保存图像时添加 toast Eclipse

javascript - 允许在 JQUERY 类中单击一次

c# - TextUpdate 和 TextChanged 事件有什么区别?

Android语音识别 Intent : Listening for IP addresses

android - 单击事件不适用于 android 中的线性布局

Android点击按钮后刷新 ListView

android - 无法在新 Activity 中传递对象数组

c# - 未将对象引用设置为对象的实例...错误?