Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Новая строка в ListView при добавлении с БД, принимает значения ранее удаленной

#android #listview #animate #ontouchlistener


Есть список на основе ListView и SimpleCursorAdapter и SQLite.  

Пишу Swipe строки списка с помощью анимации. В ACTION_MOVE строка списка должна двигаться
влево за пальцем и при достижении определенного значения по оси X менять цвет и ставать
доступной для удаления. В этой зоне при ACTION_UP строка должна удалиться с БД по найденому
ID. Соответствующе в перерисованом ListView строка с удаляемой позицией исчезает из
списка на экране.  Все это работает, но возникает следующая проблемма:

При добавлении в БД новой строки она появляется в списке на экране в том состоянии
и в том положении по оси X которое было у ранее удаленной строки.

Предполагаю что, скорее всего, где-то ListView держит ранее использованные вьюхи
с теми характеристиками с которыми они были ранее удалены и заливает туда новые строки
с БД.

Пробовал применять после удаления: notifyDataSetChanged(), завершение анимации -
эффекта нет.

    public class MainActivity extends AppCompatActivity implements View.OnClickListener,
    View.OnTouchListener, LoaderManager.LoaderCallbacks {

DB db;
DBHelper dbHelper;
SimpleCursorAdapter scAdapter;
Context context;
String name;
String kind;

private View onTouchedItemView;

ListView lv_list;
Button btnEmpty, btnAdd, btnRead, btnClear;
TextView tvNameId, tvNameName, tvNameKind, tvNameCost;
EditText tvName, tvKind;

private int pointDownX;
private int pointDownY;
private long touchedItemID;

private int targetPoint;

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

    db = new DB(this);
    db.open();

    String[] from = new String[]{DB.KEY_ID, DB.KEY_NAME, DB.KEY_KIND, DB.KEY_COST};
    int[] to = new int[]{R.id.tvListId, R.id.tvListName, R.id.tvListKind, R.id.tvListCost};

    scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);

    lv_list = (ListView) findViewById(R.id.lv_list);
    lv_list.setAdapter(scAdapter);

    lv_list.setOnTouchListener(this);
    getSupportLoaderManager().initLoader(0, null, this);

    tvNameId = (TextView) findViewById(R.id.tvNameId);
    tvNameName = (TextView) findViewById(R.id.tvNameName);
    tvNameKind = (TextView) findViewById(R.id.tvNameKind);
    tvNameCost = (TextView) findViewById(R.id.tvNameCost);

    tvName = (EditText) findViewById(R.id.tvName);
    tvName.setOnClickListener(this);

    tvKind = (EditText) findViewById(R.id.tvKind);
    tvKind.setOnClickListener(this);

    btnAdd = (Button) findViewById(R.id.btnAdd);
    btnAdd.setOnClickListener(this);

    btnEmpty = (Button) findViewById(R.id.btnEmpty);
    btnEmpty.setOnClickListener(this);

    btnRead = (Button) findViewById(R.id.btnRead);
    btnRead.setOnClickListener(this);

    btnClear = (Button) findViewById(R.id.btnClear);
    btnClear.setOnClickListener(this);
}

@Override
public void onClick(View view) {
    name = tvName.getText().toString();
    kind = tvKind.getText().toString();

    switch (view.getId()) {
        case R.id.btnAdd:
            if (kind.isEmpty()) {
                kind = "1";
            }
            if (name.isEmpty()) {
                Toast.makeText(getApplicationContext(),
                        "Fill all fields", Toast.LENGTH_SHORT).show();
            } else {
                db.addRec(name, kind);
                getSupportLoaderManager().getLoader(0).forceLoad();
                tvName.setText("");
                tvKind.setText("");
            }
            break;

        case R.id.btnEmpty:
            tvName.setText("");
            tvKind.setText("");
            break;

        case R.id.btnRead:
            getSupportLoaderManager().getLoader(0).forceLoad();
            break;

        case R.id.btnClear:
            db.delAllRec();
            getSupportLoaderManager().getLoader(0).forceLoad();
            break;
    }
}

@Override
public Loader onCreateLoader(int id, Bundle bndl) {
    return new MyCursorLoader(this, db);
}

@Override
public void onLoadFinished(Loader loader, Cursor cursor) {
    scAdapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader loader) {
}


@Override
public boolean onTouch(View v, MotionEvent event) {

    int dispWidth = v.getWidth();
    int horizontalMinDistance = dispWidth / 4;
    int distFromRightBorder = dispWidth - pointDownX;
    int distToMeet = pointDownX / 10;

    switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:
            pointDownX = (int) event.getX();
            pointDownY = (int) event.getY();

            onTouchedItemView = lv_list.getChildAt(lv_list.pointToPosition(pointDownX,
pointDownY));
            touchedItemID = lv_list.pointToRowId(pointDownX, pointDownY);

            return true;

        case MotionEvent.ACTION_MOVE:
            int pointMovingX = (int) event.getX();
            int deltaX = pointDownX - pointMovingX;

            int distGone = distFromRightBorder / distToMeet * Math.abs(deltaX);

            if (deltaX < 0) {

                if (Math.abs(deltaX) < distToMeet) {
                    targetPoint = dispWidth - pointMovingX + pointDownX - distGone;

                } else {
                    targetPoint = pointMovingX;


                }
                anim();

            } else {

                if (Math.abs(deltaX) < distToMeet) {
                    targetPoint = pointMovingX - dispWidth + distFromRightBorder
- distGone;

                } else {
                    targetPoint = pointMovingX - dispWidth;

                    if (Math.abs(deltaX) > horizontalMinDistance && pointMovingX
< dispWidth / 8) {
                        onTouchedItemView.setBackgroundResource(R.color.deletemarker);

                    } else {
                        onTouchedItemView.setBackgroundResource(R.color.backgroundmain);
                    }
                }
                anim();
            }
            return true;

        case MotionEvent.ACTION_UP:
            float upX = (int) event.getRawX();

            if (upX < dispWidth / 8) {


                db.delRec(touchedItemID);


                getSupportLoaderManager().getLoader(0).forceLoad();

            } else {
                targetPoint = 0;
                anim();
            }
            return true;
    }
    return true;
}

public void anim() {
    onTouchedItemView.animate()
            .x(targetPoint)
            .setDuration(0)
            .start();
}

private static class MyCursorLoader extends CursorLoader {
    DB db;

    public MyCursorLoader(Context context, DB db) {
        super(context);
        this.db = db;
    }

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = db.getAllData();
        return cursor;
    }
}

protected void onDestroy() {
    super.onDestroy();
    db.close();
}
}



    


Ответы

Ответ 1



Нашел решение. Применил обратную анимацию перед обновлением списка. onTouchedItemView.setBackgroundResource(R.color.backgroundmain); targetPoint = 0; anim(); И метод: clearDisappearingChildren(); Он удаляет анимацию на удаленном элементе списка. В коде выглядит так: case MotionEvent.ACTION_UP: float upX = (int) event.getRawX(); if (upX < dispWidth / 8) { db.delRec(touchedItemID); lv_list.clearDisappearingChildren(); getSupportLoaderManager().getLoader(0).forceLoad(); onTouchedItemView.setBackgroundResource(R.color.backgroundmain); targetPoint = 0; anim(); } else { targetPoint = 0; anim(); } return true;

Комментариев нет:

Отправить комментарий