自定义列表视图适配器选择项目增量textview

时间:2015-09-30 08:35:19

标签: android listview android-listview

我使用https://github.com/wdullaer/SwipeActionAdapter来刷新listview上的每个项目

一旦我滑动其中一个项目,textview文本将增加到一个。如果我将滚动列表的问题,textview将返回到每个默认值为0,一些隐藏项也会递增。

onswipe事件代码:

switch (direction) {
   case SwipeDirections.DIRECTION_FAR_LEFT:
        selectedText = (TextView) getViewByPosition(position, getListView()).findViewById(R.id.txtNumber);
        selectedText.setText(String.valueOf(Integer.parseInt(selectedText.getText().toString()) + 1));
        break;

和适配器代码:

JSONArray jsonArray = null;
try {
    jsonArray = new JSONArray(data);

} catch (JSONException e) {
    e.printStackTrace();
}
String[] strArr = new String[jsonArray.length()];
ArrayList<String> arrayList = new ArrayList<String>();

for (int i = 0; i < jsonArray.length(); i++) {
    try {

        strArr[i] = jsonArray.getJSONObject(i).getString("name");
        arrayList.add(jsonArray.getString(i));

        stringAdapter = new ArrayAdapter<String>(
                this,
                R.layout.items,
                R.id.txtName,
                new ArrayList<String>(Arrays.asList(strArr))
        );

        setListAdapter(stringAdapter);
        stringAdapter.notifyDataSetChanged();


    } catch (JSONException e) {
        e.printStackTrace();
    }
}

items.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="100sp"
    android:background="@drawable/listview_style"
    android:padding="8dp"
    android:descendantFocusability="blocksDescendants">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@mipmap/ic_launcher"
        android:layout_centerVertical="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/txtName"
        android:textSize="20sp"
        android:gravity="center"
        android:ellipsize="none"
        android:singleLine="false"
        android:scrollHorizontally="false"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20sp"
        android:layout_marginRight="20sp"
        android:layout_toRightOf="@+id/imageView"
        android:layout_toLeftOf="@+id/txtNumber"
        android:layout_toStartOf="@+id/txtNumber"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:id="@+id/txtNumber"
        android:textSize="25sp"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="40dp"
        android:layout_marginEnd="40dp"
        />

</RelativeLayout>

我认为项目位置无效或视图无效。 anyidea如何解决这个问题。感谢

更新 增量现在正常工作,但项目名称没有填充。见附件 item name not populating

1 个答案:

答案 0 :(得分:1)

问题是listview作弊。这是一个回收视图,所以会发生的情况是,您实际上只是拥有与目前看到的10个视图相同的视图。当您滚动得足够远以至于视图消失时,它再次显示为刚进入视图的视图。为了做到这一点,它摆脱了旧视图,要求适配器将这个被删除的视图变成看起来像新视图的东西(这对于内存和快速视图创建来说非常棒)。

这就是您的项目消失的原因,因为滚动后,使用适配器通过列表视图回收视图。如果您真的想看到这个,请尝试滑动将视图的可见性变为INVISIBLE,然后您会注意到所有地方的视图都在丢失。因为它们是相同的视图。

简而言之,滑动必须更改用于构建视图的数据。视图本身的任何更改都将被删除,或者弄乱其他视图(例如,可见性和.transform()通常不会被适配器重置),这些视图实际上只是相同的视图。

public class SwipeActivity extends AppCompatActivity {

SwipeActionAdapter mAdapter;

private class YourCustomRowEntry {
    String displayString;
    int swipes;

    public YourCustomRowEntry( String displayString, int swipes) {
        this.swipes = swipes;
        this.displayString = displayString;
    }
}

private class Holder {
    public TextView textName, textNumber;
    public ImageView imageView;
    public Holder(TextView textName, TextView textNumber, ImageView imageView) {
        this.textName = textName;
        this.textNumber = textNumber;
        this.imageView = imageView;
    }
}

ArrayList<YourCustomRowEntry> mDataYouEditThatBacksTheAdapter = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_swipe);

    for (int i = 1; i <= 200; i++) {
        mDataYouEditThatBacksTheAdapter.add(new YourCustomRowEntry("Row " + i,0));
    }

    BaseAdapter customAdapter = new BaseAdapter() {
        @Override
        public int getCount() {
            return mDataYouEditThatBacksTheAdapter.size();
        }

        @Override
        public Object getItem(int position) {
            return mDataYouEditThatBacksTheAdapter.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View itemView;
            Holder viewHolder;
            if (convertView != null) {
                itemView = convertView; //if you already made this view, and it's being recycled use that.
                viewHolder = (Holder)convertView.getTag(); //And fetch the already findByViews things.
            }
            else {
                //if this is the first time, inflate the view.
                itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
                TextView textName = (TextView)itemView.findViewById(R.id.txtName);
                TextView textNumber = (TextView)itemView.findViewById(R.id.txtNumber);
                ImageView imageView =  (ImageView)itemView.findViewById(R.id.imageView);
                viewHolder = new Holder(textName,textNumber,imageView);
                itemView.setTag(viewHolder); //store the data in the view's tag.
            }
            YourCustomRowEntry ycre = mDataYouEditThatBacksTheAdapter.get(position);
            viewHolder.textName.setText(ycre.displayString);
            viewHolder.textNumber.setText("" + ycre.swipes); // Gotta tell it that this is a string and not a resource.
            //You would also set the imageView from the saved set of data here too.
            return itemView;
        }
    };

    ListView listView = (ListView)findViewById(R.id.myActivitysListView);

    // Wrap your content in a SwipeActionAdapter
    mAdapter = new SwipeActionAdapter(customAdapter);

    // Pass a reference of your ListView to the SwipeActionAdapter
    mAdapter.setListView(listView);

    // Set the SwipeActionAdapter as the Adapter for your ListView
    listView.setAdapter(mAdapter);

    // Listen to swipes
    mAdapter.setSwipeActionListener(new SwipeActionAdapter.SwipeActionListener() {
        @Override
        public boolean hasActions(int position) {
            // All items can be swiped
            return true;
        }

        @Override
        public boolean shouldDismiss(int position, int direction) {
            // Only dismiss an item when swiping normal left
            return false;
            //return direction == SwipeDirections.DIRECTION_NORMAL_LEFT;
        }

        @Override
        public void onSwipe(int[] positionList, int[] directionList) {
            for (int i = 0; i < positionList.length; i++) {
                int direction = directionList[i];
                int position = positionList[i];
                switch (direction) {
                    case SwipeDirections.DIRECTION_FAR_LEFT:
                        mDataYouEditThatBacksTheAdapter.get(position).swipes++; //add 1 to swipes;
                        mAdapter.notifyDataSetChanged();
                        break;
                    case SwipeDirections.DIRECTION_FAR_RIGHT:
                        mDataYouEditThatBacksTheAdapter.get(position).swipes--; //subtract 1 to swipes;
                        mAdapter.notifyDataSetChanged();
                        break;
                }
            }
        }
    });


}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_swipe, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

它的视频工作: https://youtu.be/6wPF2OOKu2U

保存您用于支持列表视图的阵列。您需要拥有它,以便您可以更改它并获取适配器以构建新视图。 notifyDataSetChanged()它从它保存的原始数据结构中更新并重建视图。这意味着您需要修改该数据,而不是视图。这样就可以正确编写一个类并使用它来构建视图。