#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;
Комментариев нет:
Отправить комментарий