В таблице может быть столбец последовательностей, который дает ему уникальный первичный ключ последовательности ColumnA:
table: t1
ColumnA sequence ColumnB
1 1 abc
1 2 pqr
1 3 xyz
2 1 efg
2 2 hij
3 1 asd
И может быть создан Crosstab:
query: x1
TRANSFORM Min([columnB] & ", ") AS Expr1
SELECT t1.columnA
FROM t1
GROUP BY t1.columnA
PIVOT t1.sequence;
columnA 1 2 3
1 abc, pqr, xyz,
2 efg, hij,
3 asd,
Затем окончательный запрос может объединить столбцы и удалить последнюю запятую:
SELECT x1.columnA, Left([1] & [2] & [3],Len([1] & [2] & [3])-2) AS columnB FROM x1;
columnA columnB
1 abc, pqr, xyz
2 efg, hij
3 asd
Чтобы автоматизировать заполнение последовательности, можно использовать следующий код VBA:
Sub fill_sequence_t1()
Dim i: i = 1
Do While DCount("*", "t1", "sequence IS NULL") > 0
DoCmd.RunSQL "SELECT t1.columnA, Min(t1.columnB) AS columnB_min INTO t2" & _
" FROM t1 WHERE t1.sequence IS NULL GROUP BY t1.columnA;"
DoCmd.RunSQL "UPDATE t1 INNER JOIN t2 ON (t1.columnA = t2.columnA)" & _
" AND (t1.columnB = t2.columnB_min) SET t1.sequence=" & i
CurrentDb.TableDefs.Delete "t2"
i = i + 1
Loop
End Sub
сначала необходимо создать 2 расположения xml. после той внутренней части recyclerview адаптер, TYPE_CALL и TYPE_EMAIL являются двумя статическими значениями с 1 и 2 соответственно в классе адаптера.
теперь Определяют два статических значения †‹вЂ‹ на уровне класса Адаптера представления Recycler, например: частный статический международный TYPE_CALL = 1; частный статический международный TYPE_EMAIL = 2;
Теперь создают держателя представления с несколькими представлениями как это:
class CallViewHolder extends RecyclerView.ViewHolder {
private TextView txtName;
private TextView txtAddress;
CallViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtAddress = itemView.findViewById(R.id.txtAddress);
}
}
class EmailViewHolder extends RecyclerView.ViewHolder {
private TextView txtName;
private TextView txtAddress;
EmailViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtAddress = itemView.findViewById(R.id.txtAddress);
}
}
Теперь код как ниже в onCreateViewHolder и onBindViewHolder методе в recyclerview адаптере:
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view;
if (viewType == TYPE_CALL) { // for call layout
view = LayoutInflater.from(context).inflate(R.layout.item_call, viewGroup, false);
return new CallViewHolder(view);
} else { // for email layout
view = LayoutInflater.from(context).inflate(R.layout.item_email, viewGroup, false);
return new EmailViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
if (getItemViewType(position) == TYPE_CALL) {
((CallViewHolder) viewHolder).setCallDetails(employees.get(position));
} else {
((EmailViewHolder) viewHolder).setEmailDetails(employees.get(position));
}
}
Если Вы хотите использовать его в сочетании с Привязкой данных Android, изучают https://github.com/evant/binding-collection-adapter - это - безусловно лучшее решение для нескольких типов представления RecyclerView
, я даже видел.
можно использовать его как [1 110]
var items: AsyncDiffPagedObservableList<BaseListItem> =
AsyncDiffPagedObservableList(GenericDiff)
val onItemBind: OnItemBind<BaseListItem> =
OnItemBind { itemBinding, _, item -> itemBinding.set(BR.item, item.layoutRes) }
и затем в расположении, где список
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:enableAnimations="@{false}"
app:scrollToPosition="@{viewModel.scrollPosition}"
app:itemBinding="@{viewModel.onItemBind}"
app:items="@{viewModel.items}"
app:reverseLayoutManager="@{true}"/>
элементы списка должны реализовать BaseListItem
интерфейс, который похож на это
interface BaseListItem {
val layoutRes: Int
}
, и представление объекта должно выглядеть примерно так
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="...presentation.somescreen.list.YourListItem"/>
</data>
...
</layout>
, Где YourListItem
реализации BaseListItem
Hope это поможет кому-то.
Хотя выбранный ответ корректен, я просто хочу далее разработать его. Я нашел здесь полезное Пользовательский адаптер для нескольких Типов Представления в RecyclerView. версия Kotlin здесь .
Пользовательский адаптер следует
public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
ArrayList<String> list; // ArrayList of your Data Model
final int VIEW_TYPE_ONE = 1;
final int VIEW_TYPE_TWO = 2;
public CustomAdapter(Context context, ArrayList<String> list) { // you can pass other parameters in constructor
this.context = context;
this.list = list;
}
private class ViewHolder1 extends RecyclerView.ViewHolder {
TextView yourView;
ViewHolder1(final View itemView) {
super(itemView);
yourView = itemView.findViewById(R.id.yourView); // Initialize your All views prensent in list items
}
void bind(int position) {
// This method will be called anytime a list item is created or update its data
//Do your stuff here
yourView.setText(list.get(position));
}
}
private class ViewHolder2 extends RecyclerView.ViewHolder {
TextView yourView;
ViewHolder2(final View itemView) {
super(itemView);
yourView = itemView.findViewById(R.id.yourView); // Initialize your All views prensent in list items
}
void bind(int position) {
// This method will be called anytime a list item is created or update its data
//Do your stuff here
yourView.setText(list.get(position));
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ONE) {
return new ViewHolder1(LayoutInflater.from(context).inflate(R.layout.your_list_item_1, parent, false));
}
//if its not VIEW_TYPE_ONE then its VIEW_TYPE_TWO
return new ViewHolder2(LayoutInflater.from(context).inflate(R.layout.your_list_item_2, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (list.get(position).type == Something) { // put your condition, according to your requirements
((ViewHolder1) holder).bind(position);
} else {
((ViewHolder2) holder).bind(position);
}
}
@Override
public int getItemCount() {
return list.size();
}
@Override
public int getItemViewType(int position) {
// here you can get decide from your model's ArrayList, which type of view you need to load. Like
if (list.get(position).type == Something) { // put your condition, according to your requirements
return VIEW_TYPE_ONE;
}
return VIEW_TYPE_TWO;
}
}