Страницы

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

вторник, 12 февраля 2019 г.

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

Есть список на основе 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(); } }


Ответ

Нашел решение.
Применил обратную анимацию перед обновлением списка.
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;

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

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