【问题标题】:Android View won't scroll with swipe gesture and won't scroll. Using ListView with ArrayAdapterAndroid View 不会通过滑动手势滚动,也不会滚动。将 ListView 与 ArrayAdapter 一起使用
【发布时间】:2012-05-30 13:40:45
【问题描述】:

我正在为我的ListView 使用自定义ArrayAdapter。我在左侧有一个CheckBox,在CheckBox 的右侧有两个TextView 项目,它们相互堆叠。我也在使用自定义的android:listSelector

我在 MyActivity onCreate 方法中将 8 个项目插入到我的自定义 ListView 中。

我可以选择列表中的一行来改变颜色,我还可以选中和取消选中复选框。但是,视图不会响应垂直滑动,当我用手指将鼠标悬停在项目上时,它也不会给项目焦点。如果我同时单击该项目并用另一根手指向下滚动,我可以滚动,但这不是我想要的。我是否以某种方式破坏了垂直滑动手势?

我想指出我的问题中没有 ScrollView 对象。大多数帖子都与将ListView 对象放在ScrollView 中的人有关,反之亦然。

我怀疑我的布局有问题和/或我在布局和代码中分配焦点的方式有问题。

这是我的主要活动代码:

import java.util.ArrayList;    
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;


public class MyActivity extends Activity{
    private ListView lv;
    private TextView titleDisplay;
    private TextView locationDisplay;
    private ArrayList<TalkItem> m_talks = null;
    private MyListView m_adapter;

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

        lv = (ListView) findViewById(R.id.sessionlist);    
        titleDisplay = (TextView) findViewById(R.id.sessiontitle);
        locationDisplay = (TextView) findViewById(R.id.sessionlocation);

        m_talks = new ArrayList<TalkItem>();
        this.m_adapter = new MyListView(this, R.layout.sessionlistitem, m_talks);
        lv.setAdapter(this.m_adapter); 

        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                //TODO: do something
            }
        });

        //set title and location display
        titleDisplay.setText("TITLE");
        locationDisplay.setText("LOCATION");
        m_talks.add(new TalkItem("first1", "last1", false));
        m_talks.add(new TalkItem("first2", "last2", false));
        m_talks.add(new TalkItem("first3", "last3", false));
        m_talks.add(new TalkItem("first4", "last4", false));
        m_talks.add(new TalkItem("first5", "last5", false));
        m_talks.add(new TalkItem("first6", "last6", false));
        m_talks.add(new TalkItem("first7", "last7", false));
        m_talks.add(new TalkItem("first8", "last8", false));

    }

    public class MyListView extends ArrayAdapter<TalkItem> {

        private ArrayList<TalkItem> items;

        public MyListView(Context context, int textViewResourceId, 
                ArrayList<TalkItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            TalkItem talkItem = items.get(position);
            CheckBox checkBox;
            TextView topText;
            TextView bottomText;

            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.sessionlistitem, null);
                checkBox = (CheckBox) convertView.findViewById(R.id.icon);
                topText =  (TextView) convertView.findViewById(R.id.toptext);
                bottomText = (TextView) convertView.findViewById(R.id.bottomtext);

                // Optimization: Tag the row with it's child views, so we don't have to 
                // call findViewById() later when we reuse the row.
                convertView.setTag(new TalkItemViewHolder(checkBox, topText, bottomText));

                // If CheckBox is toggled, update the listitem it is tagged with.
                checkBox.setOnClickListener( new View.OnClickListener() {
                    public void onClick(View v) {
                        CheckBox cb = (CheckBox) v ;
                        TalkItem ti = (TalkItem) cb.getTag();
                        ti.setChecked( cb.isChecked() );
                    }
                });
            }
            // Reuse existing row view
            else {
                // Because we use a ViewHolder, we avoid having to call findViewById().
                TalkItemViewHolder viewHolder = (TalkItemViewHolder) convertView.getTag();
                checkBox = viewHolder.getCheckBox();
                topText = viewHolder.getTopText();
                bottomText = viewHolder.getBottomText();
            }


            // Tag the CheckBox with the Planet it is displaying, so that we can
            // access the planet in onClick() when the CheckBox is toggled.
            if(talkItem!=null){
                if(checkBox!=null){
                    checkBox.setTag(talkItem); 
                    // Display item data
                    checkBox.setChecked( talkItem.isChecked() );
                }
                if(topText!=null)
                    topText.setText(talkItem.getAuthor());
                if(bottomText!=null)
                    bottomText.setText(talkItem.getTitle());
            } 
            convertView.setBackgroundResource(android.R.color.transparent);              
            return convertView;
        }     
    }
    public class TalkItemViewHolder {
        private CheckBox checkBox;
        private TextView topText;
        private TextView bottomText;

        public TalkItemViewHolder(){}
        public TalkItemViewHolder(CheckBox checkBox, TextView topText, TextView bottomText){
            this.checkBox = checkBox;
            this.topText = topText;
            this.bottomText = bottomText;
        }

        public CheckBox getCheckBox(){
            return checkBox;
        }

        public TextView getTopText(){
            return topText;
        }

        public TextView getBottomText(){
            return bottomText;
        }

        public void setCheckBox(CheckBox checkBox){
            this.checkBox = checkBox;
        }

        public void setTopText(TextView topText){
            this.topText = topText;
        }

        public void setBottomText(TextView bottomText){
            this.bottomText = bottomText;
        }

    }

    public class TalkItem {
        private String title;
        private String author;
        private boolean checked = false;


        public TalkItem(){
            title = "";
            author = "";
        }
        public TalkItem(String title, String author, boolean checked){
            this.title = title;
            this.author = author;
            this.checked = checked;
        }

        public String getTitle(){
            return title;
        }

        public String getAuthor(){
            return author;
        }

        public void setTitle(String title){
            this.title = title;
        }

        public void setAuthor(String author){
            this.author = author;
        }

        public boolean isChecked(){
            return checked;
        }

        public void setChecked(boolean checked){
            this.checked = checked;
        }

        public void toggleChecked(){
            checked = !checked;
        }

    }

}

这是我的主视图的父布局,标题为session_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sessionviewlayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/white"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/sessiontitle"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:textSize="20dp" />

    <TextView
        android:id="@+id/sessionlocation"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/sessiontitle"
        android:gravity="center"
        android:textSize="16dp" />

    <ListView
        android:id="@+id/sessionlist"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/sessionlocation"
        android:cacheColorHint="@color/transparent"
        android:descendantFocusability="blocksDescendants"
        android:dividerHeight="3.0sp"
        android:drawSelectorOnTop="false"
        android:listSelector="@drawable/list_selector"
        android:minHeight="1in" />

</RelativeLayout>

这是列表中每个项目的布局,标题为sessionlistitem.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@color/white"
    android:padding="2dip" >

    <CheckBox
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:button="@android:drawable/btn_star"
        android:focusable="false"
        android:padding="10dp" />

    <LinearLayout
        android:layout_width="0dip"
        android:layout_height="95dp"
        android:layout_weight="0.99"
        android:clickable="false"
        android:focusable="false"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/toptext"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:clickable="false"
            android:focusable="false"
            android:gravity="center_vertical"
            android:singleLine="false"
            android:textColor="@color/black"
            android:textSize="18dp" />

        <TextView
            android:id="@+id/bottomtext"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:clickable="false"
            android:ellipsize="marquee"
            android:focusable="false"
            android:singleLine="false"
            android:textColor="@color/black"
            android:textSize="16dp" />
    </LinearLayout>

</LinearLayout>

我的自定义 listSelector list_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_pressed" />
    <item
        android:state_focused="true"
        android:drawable="@drawable/list_selector_pressed" />
    <item
        android:drawable="@android:color/transparent" />
</selector>

list_selector_pressed.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/blue"/>   
</shape>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World!</string>
    <string name="app_name">My APP</string>
    <color name="gray">#aaaaaa</color>
    <color name="white">#ffffff</color>
    <color name="blue">#5BB5D7</color>
    <color name="transparent">#00000000</color>
    <color name="black">#000000</color>
</resources>

【问题讨论】:

  • 在某处回收的视图中,您的适配器确实有问题,但如果是这样,我看不出在哪里......
  • 滚动动作是否需要以特定方式启用焦点?

标签: java android android-listview android-arrayadapter swipe


【解决方案1】:

ArrayAdapter 需要在添加完所有内容后进行初始化。具体来说,以下几行:

this.m_adapter = new MyListView(this, R.layout.sessionlistitem, m_talks);
lv.setAdapter(this.m_adapter); 

应该是 onCreate 方法的最后几行,在所有 m_talks.add(...) 之后。

xml 布局文件没有任何问题。

【讨论】:

    【解决方案2】:

    我相信问题是由于在相对布局中将列表视图高度设置为 wrap_content 引起的。这对于列表视图来说没有什么意义,因为它的内容通常大于它的屏幕高度。一种可能的解决方法是将顶部的 RelativeLayout 更改为 LinearLayout,然后列表视图上的高度设置可以是:

    android:layout_height="0dp"
    android:layout_weight="1"
    

    这将使用列表视图的所有剩余空间。

    【讨论】:

    • 它有什么效果,还是完全一样?您也可以尝试设置一个小的静态高度作为测试,例如 50dp,看看您是否看到任何滚动。如果不是,那么它可能是别的东西。
    • 哎呀,我实际上可以滚动,但不像普通的 listView。我正在使用模拟器,只有在按住单击按钮并扫动手指时才能滚动。默认的 ListView 在屏幕上以扫动的方式滚动。但我的应用程序没有。一个可能相关的问题是,当我的手指悬停在行项目上时,我还希望我的行聚焦并改变颜色。
    • 我编辑了主要条目以重新表述我的问题,即专注于 ListView 项目并使用扫掠动作滚动。
    猜你喜欢
    • 2020-06-04
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多