Ответ 1
У GridView есть метод invalidateViews().
когда вы вызываете этот метод: "все виды, которые нужно перестроить и перерисовать". http://developer.android.com/reference/android/widget/GridView.html
Я думаю, что это то, что вам нужно:)
У меня есть GridView, который очень похож на учебник Google, за исключением того, что я хочу добавить ImageViews во время выполнения (через subactivity). Результаты в порядке, но макет View перепутался: GridView не заполняет содержимое своего родителя, что мне нужно сделать для его правильной разработки?
Здесь приведен код добавления детей:
public void initializeWorkbench(GridView gv, Vector<String> items) {
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
Prototype.workbench.activateWorkbench();
// this measures the workbench correctly
Log.d(Prototype.TAG, "workbench width: "+Prototype.workbench.getMeasuredWidth());
// 320
Log.d(Prototype.TAG, "workbench height: "+Prototype.workbench.getMeasuredHeight());
// 30
ImageAdapter imgAdapter = new ImageAdapter(this.getContext(), items);
gv.setAdapter(imgAdapter);
gv.measure(screenWidth, screenHeight);
gv.requestLayout();
gv.forceLayout();
Log.d(Prototype.TAG, "gv width: "+gv.getMeasuredWidth());
// 22
Log.d(Prototype.TAG, "gv height: "+gv.getMeasuredHeight());
// 119
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
}
}
activateWorkbench, setDimension и измерение в верстаке (LinearLayout над GridView):
public void activateWorkbench() {
if(this.equals(Prototype.workbench)) {
this.setOrientation(VERTICAL);
show = true;
measure();
}
}
public void setDimension(int w, int h) {
width = w;
height = h;
this.setLayoutParams(new LinearLayout.LayoutParams(width, height));
this.invalidate();
}
private void measure() {
if (this.getOrientation() == LinearLayout.VERTICAL) {
int h = 0;
int w = 0;
this.measureChildren(0, 0);
for (int i = 0; i < this.getChildCount(); i++) {
View v = this.getChildAt(i);
h += v.getMeasuredHeight();
w = (w < v.getMeasuredWidth()) ? v.getMeasuredWidth() : w;
}
if (this.equals(Prototype.tagarea))
height = (h < height) ? height : h;
if (this.equals(Prototype.tagarea))
width = (w < width) ? width : w;
}
this.setMeasuredDimension(width, height);
}
Конструктор ImageAdapter:
public ImageAdapter(Context c, Vector<String> items) {
mContext = c;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
if (mExternalStorageAvailable && mExternalStorageWriteable) {
for (String item : items) {
File f = new File(item);
if (f.exists()) {
try {
FileInputStream fis = new FileInputStream(f);
Bitmap b = BitmapFactory.decodeStream(fis);
bitmaps.add(b);
files.add(f);
} catch (FileNotFoundException e) {
Log.e(Prototype.TAG, "", e);
}
}
}
}
}
И макет xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="bottom"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingRight="0px">
<com.unimelb.pt3.ui.TransparentPanel
android:id="@+id/workbench"
android:layout_width="fill_parent"
android:layout_height="10px"
android:paddingTop="0px"
android:paddingLeft="0px"
android:paddingBottom="0px"
android:paddingRight="0px">
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center" />
</com.unimelb.pt3.ui.TransparentPanel>
</LinearLayout>
У GridView есть метод invalidateViews().
когда вы вызываете этот метод: "все виды, которые нужно перестроить и перерисовать". http://developer.android.com/reference/android/widget/GridView.html
Я думаю, что это то, что вам нужно:)
Сначала вы должны сообщить адаптеру о том, что данные были изменены, и снова установите адаптер в сетку.
adapter.notifyDataChanged();
grid.setAdapter(adapter);
Это может быть полезно. Я обновляю gridview эскизов изображений книги после того, как удаление будет выполнено над элементом. Использование adapter.notifyDataChanged(); как упоминалось выше, не работает для меня, поскольку он вызвал в моем адаптере.
//this is a call that retrieves cached data.
//your constructor can be designed and used without it.
final Object data = getLastNonConfigurationInstance();
Я по существу просто перезаряжаю адаптер и привязываю его к тому же самому виду.
//reload the adapter
adapter = new BooksAdapter(MyBooks.this, MyBooks.this, data, show_collection );
grid.invalidateViews();
grid.setAdapter(adapter);
@flyerz @snagnever
Вместе вы, ребята, получили его. Это должно быть:
adapter.notifyDataChanged();
grid.invalidateViews();
Это означает, что адаптер изменил свои данные, который затем будет передаваться в сетку всякий раз, когда вызывается метод invalidateViews().
Рад, что я нашел этот вопрос, потому что я не мог понять, как добавить элементы в сетку после его рендеринга.
Ни один из этих ответов на самом деле не работал у меня, и мне пришлось смять все вместе. Чтобы получить обновление GridView, вам необходимо сделать следующее:
adapter.notifyDataChanged();
grid.invalidateViews();
grid.setAdapter(adapter);
Надеюсь, это поможет любому, кто не сможет заставить другие решения работать.
Вы не должны звонить invalidateViews
и setAdapter
, чтобы обновить grid view
. Не рекомендуется обновлять grid view
, если вы обновляете таким образом, это потребует большого времени и памяти.
Если у вас есть возможность взглянуть на метод getView
, вы увидите, что convertView
создается только один раз. Когда вы вызываете notifyDataChanged
, он обновит это представление. Если вы вызываете invalidateViews
, ранее созданные представления будут воссозданы. Это нехорошее решение.
Ваш метод getView
вызывается при вызове notifyDataChanged
. Таким образом, ваш метод getView должен выглядеть примерно так, как показано ниже.
public List list;
public class SimpleItemViewHolder extends Object
{
public TextView textView;
public ImageView imageView;
}
public View getView(int position, View convertView, ViewGroup parent){
View itemView = convertView;
SimpleItemViewHolder viewHolder;
if(convertView==null)
{
viewHolder = (SimpleItemViewHolder)itemView.getTag();
}else{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.layout_name, null);
TextView labelField = (TextView) itemView.findViewById(R.id.label_field);
labelField.setText(list.get(position).Name);
//Typeface boldFont = Typeface.createFromAsset(context.getAssets(), "fonts/Font-Bold.ttf");
//labelField.setTypeface(boldFont);
ImageView imageView = (ImageView) itemView.findViewById(R.id.image_view);
//Bitmap bitmap = init your bitmap here;
//imageView.setImageBitmap(bitmap);
viewHolder = new SimpleItemViewHolder();
viewHolder.imageView = imageView;
viewHolder.textView = labelField;
itemView.setTag(viewHolder);
}
//don't create new views, instead use previous ones and update them.
viewHolder.textView.setText(list.get(position).Name);
//viewHolder.imageView.setImageBitmap(your_bitmap);
return itemView;
}
adapter.notifyDataChanged();
может не работать только потому, что данные для адаптера устарели (если активность или фрагмент не были уничтожены и, например, сидят в заднем стеке).
Итак, если сначала обновить данные, то после того, как он будет работать.
Вы размещаете GridView
внутри com.unimelb.pt3.ui.TransparentPanel
, который 10px
высокий.
px
, вы должны использовать dp
.com.unimelb.pt3.ui.TransparentPanel
android:layout_height="10px"
на android:layout_height="fill_parent"
В вашем адаптере:
class MAdapter extends BaseAdapter{
List<Objects> mObjects;
...
public void clearAdapter(){
mObjects.clear();
}
public void addNewValues(List<Objects> mObjects){
this.mObjects = mObjects;
}
...
}
adapter.clearAdapter(); // clear old values
adapter.addNewValues(MObjects);
adapter.notifyDataChanged();