Ответ 1
Вы можете использовать StaggeredGridLayoutManager.LayoutParams
для изменения ширины и высоты ячеек. То, что вы ожидаете от проектирования, следует по простому шаблону. Если вы назначаете каждой ячейке индекс (в порядке, в котором StaggeredGridLayoutManager
упорядочивает их по умолчанию), вы будете иметь это:
index % 4 == 3 ---> full span cell
index % 8 == 0, 5 ---> half span cell
index % 8 == 1, 2, 4, 6 ---> quarter span cell
сначала объявить некоторые константы в адаптере для определения типов span:
private static final int TYPE_FULL = 0;
private static final int TYPE_HALF = 1;
private static final int TYPE_QUARTER = 2;
Затем переопределите метод getItemViewType
в вашем адаптере следующим образом:
@Override
public int getItemViewType(int position) {
final int modeEight = position % 8;
switch (modeEight) {
case 0:
case 5:
return TYPE_HALF;
case 1:
case 2:
case 4:
case 6:
return TYPE_QUARTER;
}
return TYPE_FULL;
}
Все, что вам нужно сделать, это изменить layoutparams с учетом viewType
holder
:
@Override
public MyHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final View itemView =
LayoutInflater.from(mContext).inflate(R.layout.items, parent, false);
itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
final int type = viewType;
final ViewGroup.LayoutParams lp = itemView.getLayoutParams();
if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {
StaggeredGridLayoutManager.LayoutParams sglp =
(StaggeredGridLayoutManager.LayoutParams) lp;
switch (type) {
case TYPE_FULL:
sglp.setFullSpan(true);
break;
case TYPE_HALF:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
break;
case TYPE_QUARTER:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
sglp.height = itemView.getHeight() / 2;
break;
}
itemView.setLayoutParams(sglp);
final StaggeredGridLayoutManager lm =
(StaggeredGridLayoutManager) ((RecyclerView) parent).getLayoutManager();
lm.invalidateSpanAssignments();
}
itemView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
MyHolder holder = new MyHolder(itemView);
return holder;
}
Мой адаптер всегда возвращает 50 для количества элементов (просто тест), и я использовал простой файл макета для элементов. Он содержит LinearLayout
и TextView
, чтобы показать позицию владельца. Помните, что вы должны передать 2 для spanCount
(int the StaggeredGridLayoutManager
конструктор) из-за вашей конструкции.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
StaggeredGridLayoutManager lm =
new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(lm);
rv.setAdapter(new MyAdapter(this));
}
PS:
Для ленивых людей, подобных мне, может быть, это более простой способ, чем расширение моего пользовательского LayoutManager
, но я уверен, что есть лучшие способы достичь этого.
Обновление:
Обновленная часть вашего вопроса более проста, вы можете использовать GridLayoutManager
:
GridLayoutManager glm = new GridLayoutManager(this, 3);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position % 3 == 2) {
return 3;
}
switch (position % 4) {
case 1:
case 3:
return 1;
case 0:
case 2:
return 2;
default:
//never gonna happen
return -1 ;
}
}
});
rv.setLayoutManager(glm);
Таким образом вы устанавливаете 3 для размера диапазона по умолчанию, затем, учитывая положение своего диапазона, каждый элемент занимает 1, 2 или 3 пролета, что-то вроде этого:
Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1.width