Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
gelios_oleg
1 / 1 / 0
Регистрация: 01.02.2016
Сообщений: 13
#1

Восстановление позиции ListView по возвращении из другого Activity - Программирование Android

17.04.2016, 01:19. Просмотров 738. Ответов 13

Доброго времени суток.

Имеется activity с ListView, заполняемого из базы данных. При нажатии элемента идёт переход на новое активити с передачей в него данных. По возвращении обратно хотелось бы, чтобы позиция списка сохранялась. Пересмотрел кучу ответов и пробовал все варианты - ни один не работает, при возвращении список отображается сначала, уже не знаю как решить проблему. Последний вариант выглядит так:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.FilterQueryProvider;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import java.sql.SQLException;
 
public class ElectroActivity extends AppCompatActivity {
 
    EditText objectFilter;
    ListView objectList;
    DatabaseHelper sqlHelper;
    Cursor userCursor;
    SimpleCursorAdapter userAdapter;
    //Parcelable state;
    private static final String LIST_STATE = "listState";
    private Parcelable mListState = null;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_electro);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 
        objectFilter = (EditText)findViewById(R.id.objectFilter);
        objectList = (ListView)findViewById(R.id.objectList);
        sqlHelper = new DatabaseHelper(getApplicationContext());
        // создаем базу данных
        sqlHelper.create_db();
       }
 
    @Override
    protected void onRestoreInstanceState(Bundle state) {
        super.onRestoreInstanceState(state);
        mListState = state.getParcelable(LIST_STATE);
    }
 
    @Override
    public void onResume(){
        super.onResume();
        try {
            sqlHelper.open();
            userCursor = sqlHelper.database.rawQuery("select * from " + DatabaseHelper.TABLE, null);
            String[] headers = new String[]{DatabaseHelper.COLUMN_NAME, DatabaseHelper.COLUMN_ENERGY,
                DatabaseHelper.COLUMN_SET, DatabaseHelper.COLUMN_ID};
            userAdapter = new SimpleCursorAdapter(this, R.layout.my_list_item,
                userCursor, headers, new int[]{R.id.textname, R.id.textenergy, R.id.textset}, 0);
 
            objectList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Cursor cursor = (Cursor)objectList.getItemAtPosition(position);
 
                    Intent intent = new Intent(getApplicationContext(), ElDataActivity.class);
                    //intent.putExtra("id",cursor.getString(userCursor.getColumnIndex("_id")));
                    intent.putExtra("object", cursor.getString(userCursor.getColumnIndex("objects")));
                    intent.putExtra("balans", cursor.getString(userCursor.getColumnIndex("balans")));
                    intent.putExtra("napr", cursor.getString(userCursor.getColumnIndex("napr")));
                    intent.putExtra("numTP", cursor.getString(userCursor.getColumnIndex("numTP")));
                    intent.putExtra("numTR", cursor.getString(userCursor.getColumnIndex("numTR")));
                    intent.putExtra("sumTR", cursor.getString(userCursor.getColumnIndex("sumTR")));
                    intent.putExtra("set", cursor.getString(userCursor.getColumnIndex("set")));
                    intent.putExtra("energy", cursor.getString(userCursor.getColumnIndex("energy")));
                    intent.putExtra("kat", cursor.getString(userCursor.getColumnIndex("kat")));
                    intent.putExtra("razr", cursor.getString(userCursor.getColumnIndex("pazr")));
                    intent.putExtra("ust", cursor.getString(userCursor.getColumnIndex("ust")));
                    /*intent.putExtra("balans", DatabaseHelper.COLUMN_BAL);*/
                    //state = objectList.onSaveInstanceState();
                    startActivity(intent);
                }
            });
 
            // если в текстовом поле есть текст, выполняем фильтрацию
            // данная проверка нужна при переходе от одной ориентации экрана к другой
            if(!objectFilter.getText().toString().isEmpty())
                userAdapter.getFilter().filter(objectFilter.getText().toString());
 
            // установка слушателя изменения текста
            objectFilter.addTextChangedListener(new TextWatcher() {
 
                public void afterTextChanged(Editable s) {
                }
 
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }
                // при изменении текста выполняем фильтрацию
                public void onTextChanged(CharSequence s, int start, int before, int count) {
 
                    userAdapter.getFilter().filter(s.toString());
                }
            });
 
            // устанавливаем провайдер фильтрации
            userAdapter.setFilterQueryProvider(new FilterQueryProvider() {
                @Override
                public Cursor runQuery(CharSequence constraint) {
 
                    if (constraint == null || constraint.length() == 0) {
 
                        return sqlHelper.database.rawQuery("select * from " + DatabaseHelper.TABLE, null);
                    } else {
                        return sqlHelper.database.rawQuery("select * from " + DatabaseHelper.TABLE + " where " +
                                DatabaseHelper.COLUMN_NAME + " like ?", new String[]{"%" + constraint.toString() + "%"});
                    }
                }
            });
 
            //сохраняем положение ListView
            //Parcelable state = objectList.onSaveInstanceState();
 
            //обновляем ListView
            if (mListState != null) {
                objectList.onRestoreInstanceState(mListState);
                mListState = null;
            }
            objectList.setAdapter(userAdapter);
 
            //Восстанавливаем положение ListView
            //objectList.onRestoreInstanceState(state);
            //if(state != null) {
            //    objectList.onRestoreInstanceState(state);
            //}
            //userAdapter.notifyDataSetChanged();
 
        }
        catch (SQLException ex){}
    }
 
    @Override
    protected void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        mListState = objectList.onSaveInstanceState();
        state.putParcelable(LIST_STATE, mListState);
    }
 
    /*@Override
    public void onPause() {
        state = objectList.onSaveInstanceState();
        super.onPause();
    }*/
 
    @Override
    public void onDestroy(){
        super.onDestroy();
        // Закрываем подключения
        sqlHelper.database.close();
        userCursor.close();
        //state = objectList.onSaveInstanceState();
    }
 
}
Подскажите, в чем загвоздка?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
17.04.2016, 11:57     Восстановление позиции ListView по возвращении из другого Activity #2
gelios_oleg, привет!
Не стал разбираться в коде, делал когда-то такое, всё работало. И для активностей, и для фрагментов тоже можно придумать.
Если идти по простому варианту, то надо открывать одну активность из другой через startActivityForResult. По окончании ловить событие возврата через onActivityResult. Туда и обратно передавать позицию в списке. Можно было бы сохранять её в самой вызывающей активности, но она может уничтожиться.
Восстановление и получение позиции в списке делается двумя методами. Первый прокручивает к нужному месту, второй тоже не помню, как называется.
gelios_oleg
1 / 1 / 0
Регистрация: 01.02.2016
Сообщений: 13
17.04.2016, 23:35  [ТС]     Восстановление позиции ListView по возвращении из другого Activity #3
Спасибо за совет, я глядел в сторону startActivityForResult, но юоюсь мне не совсем подходит, так как на ListView я возвращаюсь кнопкой Назад, то есть результат потеряется.

Добавлено через 5 часов 35 минут
Попробовал запихать в finish():
Java
1
2
3
4
5
6
7
    @Override
    public void finish() {
        Intent intent = new Intent();
        intent.putExtra("pos", pos);
        setResult(RESULT_OK, intent);
        super.finish();
    }
Но на выходе ничего не получаю:
Java
1
2
3
4
5
6
7
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (data == null) {return;}
        posBack = data.getIntExtra("pos", posBack);
        Log.i("!!!!!!!", "Возврат на ");
        Log.i("!!!!!!!", Integer.toString(posBack));
    }
Что-то я точно делаю неправильно. Да с listView ухожу в интент:
Java
1
2
3
final int REQUEST_CODE = 1;
 
startActivityForResult(intent, REQUEST_CODE);
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
18.04.2016, 17:09     Восстановление позиции ListView по возвращении из другого Activity #4
gelios_oleg, не за что!
Что-то я не увидел у вас корректного кода.
Если вы вызываете одну активность из другой, можно использовать startActivityForResult, она отрабатывает всегда (сложные случаи лишь для фрагментов и ещё есть проблемный момент для фотографирования).
Открываю первую попавшуюся ссылку (http://developer.alexanderklimov.ru/...d/activity.php).
Запуск:
Java
1
2
Intent intent = new Intent(MainActivity.this, ChooseActivity.class);
startActivityForResult(intent, CHOOSE_THIEF);
Константа CHOOSE_THIEF в данном случае определяет для onActivityResult, из какой активности мы вернёмся. Можете обозвать её как угодно и присвоить любое уникальное числовое значение. Например, CHOOSE_THIEF = 100.
Дальше требуется передать в intent все необходимые параметры.
Java
1
2
3
intent.putString("что-то", value1);
intent.putBoolean("признак", true);
intent.putLong("позиция", offset);
Теперь пропишите в ChooseActivity (вместо этого названия - ваше) обработку параметров, какие-то действия и возврат.
Java
1
2
3
4
5
Intent intent = getIntent();
String user = intent.getStringExtra("что-то");
boolean b = intent.getBooleanExtra("признак");
long offset = intent.getLongExtra("позиция");
// Дальнейшая работа.
Когда задумаете возвращаться, надо прописать следующее. Во многих руководствах предлагается вернуться по кнопке, но это ахинея, потому что пользователь может вернуться по кнопке "Назад". Надо переопределить событие onBackPressed().
Java
1
2
3
4
5
6
7
 @Override
    public void onBackPressed() {
            Intent intent = new Intent();
            intent.putExtra("позиция", offset);
            setResult(RESULT_OK, intent);
        super.onBackPressed();
    }
Теперь надо словить событие onActivityResult в вызывающей активности.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
 
        switch (requestCode)
        {
            case CHOOSE_THIEF:
                if (resultCode == RESULT_OK && data != null) {
                    if (data.hasExtra("позиция")) {
                       long offset = data.getLongExtra("позиция", -1);
                       // Тут прокрутите к нужной позиции.
                    }
                }
                break;
 
            case DEFECT_PHOTO_TAKE_REQUEST_CODE:
                if (resultCode == RESULT_OK) {
                }
                break;
 
            default:
                break;
        }
    }
Код не проверял, он может не работать, делайте сами.
Pablito
2419 / 1864 / 583
Регистрация: 12.05.2014
Сообщений: 6,604
Завершенные тесты: 1
18.04.2016, 17:53     Восстановление позиции ListView по возвращении из другого Activity #5
gelios_oleg, только что создал активити с листвью
заполнил его списком, на Fab повесил старт второй активити

листаю на какую угодно позицию в листе и нажимаю fab - открывается второе активити...нажимаю Back на клавиатуре, второе активити закрывается и я вижу первое активити и список как был так и остался на том месте куда я наскорлил - не сдвинулся ни на йоту

я не понял задачу или что?
REALIST07
Автор FAQ
Автор FAQ
176 / 176 / 13
Регистрация: 11.06.2010
Сообщений: 932
18.04.2016, 18:19     Восстановление позиции ListView по возвращении из другого Activity #6
Ребят, для глобального хранения позиции подойдет наследник класса Application
Pablito
2419 / 1864 / 583
Регистрация: 12.05.2014
Сообщений: 6,604
Завершенные тесты: 1
18.04.2016, 18:28     Восстановление позиции ListView по возвращении из другого Activity #7
это и так понятно
хоть sharedpreference хоть Application
я к тому что позиция в листвью не сбрасывается когда активити возвращается из стека
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
18.04.2016, 19:13     Восстановление позиции ListView по возвращении из другого Activity #8
Цитата Сообщение от Паблито Посмотреть сообщение
и список как был так и остался на том месте куда я наскорлил - не сдвинулся ни на йоту
Это в простом случае, когда активность не пересоздаётся, а ListView не перезаполняется данными из БД.
Pablito
2419 / 1864 / 583
Регистрация: 12.05.2014
Сообщений: 6,604
Завершенные тесты: 1
18.04.2016, 20:24     Восстановление позиции ListView по возвращении из другого Activity #9
получилось запоминать-восстанавливать так

эти две переменные сохраняем как удобно - преференсы, класс приложения - куда угодно
Java
1
2
int pos; // первый видимый элемент списка
int offset; // для точного позиционирования, вдруг он виден не полностью
запоминаем позицию
Java
1
2
3
                    pos = lv.getFirstVisiblePosition();
                    View v = lv.getChildAt(0);
                    if (v != null) offset = v.getTop() - lv.getPaddingTop();
восстанавливаем
Java
1
        lv.setSelectionFromTop(pos, offset);
gelios_oleg
1 / 1 / 0
Регистрация: 01.02.2016
Сообщений: 13
19.04.2016, 01:12  [ТС]     Восстановление позиции ListView по возвращении из другого Activity #10
Всем спасибо, проблему описал видимо некорректно. Была проблема с запоминаем позиции при нажатии на кнопку "назад" в тулбаре. Как всегда всё просто на самом деле, голова была забита основными задачами (не android, и не программирование) и не мог понять толком почему не получается вариант с
Java
1
2
3
4
5
6
//сохраняем положение ListView
            Parcelable state = objectList.onSaveInstanceState();
            //формируем список
            objectList.setAdapter(userAdapter);
            //восстанавливаем положение ListView при возврате с дочернего окна
            objectList.onRestoreInstanceState(state);
Соответственно не разобравшись толком стал прыгать от варианта к варианту, в которых толком тоже не разобрался. В общем методом наскока не получилось.
Решение элементарное (причем, что забавно, что в одном из активити программы уже применял ранее, но забыл про это):
В дочернем активити запускаю:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //переопределяем действие кнопки назад на тубаре
        //для вызова onSaveInstanceState() (запоминание положение списка) в предыдущем окне
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
 
 
    @Override
    public void onBackPressed(){
        super.onBackPressed();
    }
И всё хорошо
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
19.04.2016, 09:31     Восстановление позиции ListView по возвращении из другого Activity #11
gelios_oleg, тут у вас есть лишнее, но принцип правильный. Как раз недавно мне тоже это подсказали. Раньше, как и большинство авторов, писал туда finish().
gelios_oleg
1 / 1 / 0
Регистрация: 01.02.2016
Сообщений: 13
21.04.2016, 09:44  [ТС]     Восстановление позиции ListView по возвращении из другого Activity #12
Мммм... А не подскажите, что лишнее? Я как бы не опытный программист, точнее сказать не программист, специальность смежная, а работа вообще несмежная просто решил написать для себя приложение, и разбираюсь по чуть-чуть, по урокам, книгам и гуглу. А хочется, чтобы выглядело красиво.
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
21.04.2016, 09:59     Восстановление позиции ListView по возвращении из другого Activity #13
Цитата Сообщение от gelios_oleg Посмотреть сообщение
А не подскажите, что лишнее?
Цитата Сообщение от gelios_oleg Посмотреть сообщение
@Override public void onBackPressed(){
super.onBackPressed();
}
Поскольку вы не переопределяете действия по обработке кнопки "Назад", то этот код лишний. Хорошо, что super.onBackPressed() не забыли, а то кнопка "Назад" перестала бы работать (на этом и основан принцип её отключения).
Цитата Сообщение от gelios_oleg Посмотреть сообщение
//восстанавливаем положение ListView при возврате с дочернего окна
objectList.onRestoreInstanceState(state);
Этот код мне пока не известен и я боюсь, что тут может быть проблема, если objectList = null, но тему не штудировал. Я обычно использую onSaveInstanceState. Но в данном случае это не требовалось, если есть onActivityResult.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.04.2016, 14:29     Восстановление позиции ListView по возвращении из другого Activity
Еще ссылки по теме:
Android Запуск Activity из другого apk
Передать данные из диалога ListView родительскому Activity Android
Android Как динамически заполнять ListView из другой activity?
Доступ к элементам Activity из другого класса Android
Передать данные при клике на listview в другое activity Android

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
gelios_oleg
1 / 1 / 0
Регистрация: 01.02.2016
Сообщений: 13
21.04.2016, 14:29  [ТС]     Восстановление позиции ListView по возвращении из другого Activity #14
Цитата Сообщение от gelios_oleg Посмотреть сообщение
@Override public void onBackPressed(){
super.onBackPressed();
}
Поскольку вы не переопределяете действия по обработке кнопки "Назад", то этот код лишний. Хорошо, что super.onBackPressed() не забыли, а то кнопка "Назад" перестала бы работать (на этом и основан принцип её отключения).
Да, действительно забыл убрать, во время экспериментов появилось

Цитата Сообщение от gelios_oleg Посмотреть сообщение
//восстанавливаем положение ListView при возврате с дочернего окна
objectList.onRestoreInstanceState(state);
Этот код мне пока не известен и я боюсь, что тут может быть проблема, если objectList = null, но тему не штудировал. Я обычно использую onSaveInstanceState. Но в данном случае это не требовалось, если есть onActivityResult.
Позже, я поставил проверку на null.
Yandex
Объявления
21.04.2016, 14:29     Восстановление позиции ListView по возвращении из другого Activity
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru