Добавление представлений в определенном порядке и сохранение этого порядка

У меня есть кнопка «добавить» и GridLayout с 6 слотами в ней, когда я нажимаю кнопку «добавить», view1 добавляется в gridlayout, я нажимаю кнопку «добавить», снова появляется view2 и т. Д.

if (!theLayout1.isShown()) { Grid.addView(theLayout1); } else if (!theLayout2.isShown()) { Grid.addView(theLayout2); } else if (!theLayout3.isShown() ) { Grid.addView(theLayout3); } ..... // this goes on 

После добавления представления я проверяю, был ли его текст уже добавлен в sharedPrefs, чтобы они могли автоматически добавляться при повторном создании действия

 if (prefs.getString("text4", null) != null) { Grid.addView(theLayout4); } if (prefs.getString("text5", null) != null) { Grid.addView(theLayout5); } // each view has one EditText 

Моя проблема в том, что если я удалю view1, а затем добавлю его снова, он будет помещен в последний слот, как я этого хочу, но когда я заново создаю действие, он вернется на первое место, потому что, поскольку код считывается в его То он будет добавлять представления в их первоначальном порядке.

Я хочу добавить представления при воссоздании активности в том порядке, в котором они были, до завершения деятельности, это может иметь простое логическое решение или, может быть, я просто неправильно подхожу к этой проблеме, в любом случае нужна помощь!

Прежде всего, вы можете сохранить теги представлений «или что бы вы их не отметили» в структуре данных, где есть тег и позиция, в которой находится представление, а затем сохранить код в SharedPreferences.

 public void savePreferences() { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(activity); SharedPreferences.Editor prefsEditor = mPrefs.edit(); Gson gson = new Gson(); String json = gson.toJson(dataStructure, new TypeToken<DataStructure>() { }.getType()); prefsEditor.putString("ordering", json); prefsEditor.commit(); } public static DataStructure loadPreferences() { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(activity); Gson gson = new Gson(); String json = mPrefs.getString("ordering", ""); if (!json.equals("")) { return (DataStructure) gson.fromJson(json, new TypeToken<DataStructure>() { }.getType()); } else { return new DataStructure(); } } 

Затем, когда вы извлекаете структуру данных, как указано выше, вы можете отсортировать результаты на основе своих позиций, используя следующий код:

 Arrays.sort(dataStructure , new Comparator<DataStructureElement>() { @Override public int compare(DataStructureElement o1, DataStructureElement o2) { return Integer.compare(o1.position, o2.position); } }); 

Затем перебирайте отсортированные результаты в dataStructure и обычно добавляйте представления к GridLayout.

Проблема (по крайней мере, из того, что я понял из вашего вопроса), заключается в том, что вы не сохраняете в настройках какой-то индикатор для позиции представления в своем родителе. Прямо сейчас нет никакой разницы между добавлением в первый раз и добавлением представления снова после его удаления или между добавлением вида в слот 1 и слот 5 (например). Один из способов справиться с этим был бы иметь запись в настройках для каждого из этих слотов, а затем сохранить в этих настройках слота индикатор вида:

Например:

 // the base of the slot keys, there will be 6 of them from 1 to 6 inclusive private static final String KEY_SLOT = "key_slot"; // when adding the view for slot 2 you'll save in preferences text2 it's indicator prefEditor.putString(KEY_SLOT + position, text2); // position will be 2, the indicator of the slot in your layout // when you delete the view from a slot, nullify it's slot preferences // for example deleting the slot 3(child 3 in the layout) prefEditor.putString(KEY_SLOT + position, null); position will be 3 

Когда вы воссоздаете активность, посмотрите все настройки SLOT и посмотрите, какие значения они хранят. Они могут быть нулевыми, если ваш макет позволяет иметь отверстия (например, не иметь вид для слота 2, но иметь представление для слота 1 и 3), или они могут содержать одну из ваших текстовых * переменных, указывающих, какой вид должен быть помещен в этот слот:

 // in the activity: // iterate over all the SLOT preferences for (int i = 1; i <= 6; i++) { String text = prefs.getString(KEY_SLOT + i, null); // if text is null there is no view stored for this slot // keep in mind that you need to add some sort of empty widget to act as a child // or modify the LayoutParams of the other children to take in consideration the empty space // OR // if text is one of your values, like text1, text2 etc // then you know that at slot i you need to place the view corresponding to the text value } 

Это сводится к вставке элементов в отсортированный массив. Существует метод addView(View child, int index) , который добавит представление в нужную позицию, что вы хотите использовать. Вам нужно будет перебирать добавленных детей и найти правильный индекс, в который нужно вставить новый. Если вы помечаете каждое представление своим значением перед его добавлением, вы можете посмотреть теги, чтобы определить, где находится этот индекс.

 private void insertView(View theLayoutN, int n) { // tag the new view with its value theLayoutN.setTag(Integer.valueOf(n)); // iterate over the views currently in the grid, keeping track // of the desired insertion index int insertionIndex = 0; final int childCount = grid.getChildCount(); for (int i = 0; i < childCount; i++) { // get the child currently at index i View child = grid.getChildAt(i); // retrieve its tag, which is its value int childN = ((Integer) child.getTag()).intValue(); // if the child's value is greater than the value of the // one we're inserting, then we have found the insertionIndex if (childN > n) { break; } // increment the insertionIndex insertionIndex++; } grid.addView(theLayoutN, insertionIndex); } 

Затем, когда вам нужно вставить макет, вы можете сделать это:

 if (!theLayout1.isShown()) { insertView(theLayout1, 1); } else if (!theLayout2.isShown()) { insertView(theLayout2, 2); } else if (!theLayout3.isShown()) { insertView(theLayout3, 3); } 

Это должно гарантировать, что ваши взгляды всегда в правильном порядке. Его можно было бы оптимизировать путем реализации двоичного поиска, но если у вас есть много видов, вы должны использовать ListView в любом случае.

Однако вы можете полностью пересмотреть эту архитектуру, поскольку у вас много избыточного кода, который может быть упрощен с помощью цикла или структуры данных. Кроме того, вы всегда можете добавить все представления и просто вызвать theLayout.setVisibility(View.GONE) если вы хотите скрыть ее, а также theLayout.setVisibility(View.VISIBLE) когда вы хотите ее показать.

Я бы справился с такой штукой, используя JsonArray

Всякий раз, когда вы добавляете представление, добавьте этот текст в массив json, а затем сохраните его в своем общем предпочтении в виде строки.

 jsonarray.toString() 

Вы можете легко добавлять и удалять элементы, когда ваши взгляды удаляются или добавляются. Также это поможет вам иметь только одно разделяемое предпочтение и не работать с разными настройками.

 SharedPreferences sf = ..... String txt=sf.getString("YOUR_KEY",""); JsonArray myViewArray=new JsonArray(txt); for(int i=0;i<myViewArray.length();i++){ // ADD VIEW HERE } 

Вы должны сохранить имя имя вашего макета + счетчик. Ex: Layout1, layout2, layout3 …

Когда вы хотите получить их в порядке, вам просто нужно зациклиться до тех пор, пока у вас не будет ничего, что можно извлечь:

  int i = 1; String valueStored = null; do { String key = "layout" + i; // layout1, layout2, layout3... SharedPreferences preferences = activity.getSharedPreferences(key, 0); valueStored = preferences.getString(key, null); // View v = getViewByName(valueStored) get the view by the name retrieved from the shared pref //Grid.addView(view); } while (valueStored != null); // stop when there is nothing more to get 

Надеюсь, поможет !