Android RecyclerView: измените файл макета LIST на GRID onOptionItemSelected
Я разрабатываю приложение для Android для онлайн-покупок. Я создал следующее представление для списка продуктов с помощью RecyclerView
, в котором я хочу изменить представление при выборе пункта меню:
Я создал следующий адаптер с именем ProductAdapter
, в котором я применил код для изменения макета в onCreateViewHolder
для выбора файла макета на основе логического значения.
Код адаптера ProductAdapter
:
/***
* ADAPTER for Product to binding rows in List
*/
private class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductRowHolder> {
private List<Product> productList;
private Context mContext;
public ProductAdapter(Context context, List<Product> feedItemList) {
this.productList = feedItemList;
this.mContext = context;
}
@Override
public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(isProductViewAsList ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null);
ProductRowHolder mh = new ProductRowHolder(v);
return mh;
}
@Override
public void onBindViewHolder(ProductRowHolder productRowHolder, int i) {
Product prodItem = productList.get(i);
// Picasso.with(mContext).load(feedItem.getName())
// .error(R.drawable.ic_launcher)
// .placeholder(R.drawable.ic_launcher)
// .into(productRowHolder.thumbnail);
double price = prodItem.getPrice();
double discount = prodItem.getDiscount();
double discountedPrice = price - (price * discount / 100);
String code = "";
if(prodItem.getCode() != null)
code = "[" + prodItem.getCode() + "] ";
productRowHolder.prodIsNewView.setVisibility(prodItem.getIsNew() == 1 ? View.VISIBLE : View.INVISIBLE);
productRowHolder.prodNameView.setText(code + prodItem.getName());
productRowHolder.prodOriginalRateView.setText("Rs." + new BigDecimal(price).setScale(2,RoundingMode.DOWN));
productRowHolder.prodDiscView.setText("" + new BigDecimal(discount).setScale(2,RoundingMode.DOWN) + "% off");
productRowHolder.prodDiscRateView.setText("Rs." + new BigDecimal(discountedPrice).setScale(2,RoundingMode.DOWN));
productRowHolder.prodOriginalRateView.setPaintFlags(productRowHolder.prodOriginalRateView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
@Override
public int getItemCount() {
return (null != productList ? productList.size() : 0);
}
public class ProductRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//Declaration of Views
public ProductRowHolder(View view) {
super(view);
view.setOnClickListener(this);
//Find Views
}
@Override
public void onClick(View view) {
//Onclick of row
}
}
}
После этого я сделал код для изменения RecyclerView
layout от List
до Grid
и Vice Versa в onOptionsItemSelected
, здесь я вызываю mAdapter.notifyDataSetChanged();
, чтобы он снова вызвал адаптер и изменил значение.
onOptionsItemSelected
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.action_settings:
return true;
case android.R.id.home:
finish();
break;
case R.id.product_show_as_view:
isProductViewAsList = !isProductViewAsList;
supportInvalidateOptionsMenu();
mRecyclerView.setLayoutManager(isProductViewAsList ? new LinearLayoutManager(this) : new GridLayoutManager(this, 2));
mAdapter.notifyDataSetChanged();
break;
}
return super.onOptionsItemSelected(item);
}
Я получил немного успеха, например:
Изображение макета Grid
:
Изображение макета List
:
НО ТЕПЕРЬ, КОГДА Я ПРОСМОТРЕТЬ, а затем ИЗМЕНИТЬ ПРОСМОТР Отображается, например:
Grid
макет:
List
макет:
Я не знаю, почему это происходит после прокрутки. Есть ли другой способ изменить вид, подобный этому.
Сегодня я только что увидел, что эта проблема возникает из-за ImageView
, без полноценной работы.
Помогите, пожалуйста, вам поможет.
Ответы
Ответ 1
Я нашел решение с началом активности, которое я установил LinearLayoutManager
, например:
mLayoutManager = new LinearLayoutManager(this);
mProductListRecyclerView.setLayoutManager(mLayoutManager);
после этого onOptionsItemSelected
, написанный как:
case R.id.menu_product_change_view:
isViewWithCatalog = !isViewWithCatalog;
supportInvalidateOptionsMenu();
//loading = false;
mProductListRecyclerView.setLayoutManager(isViewWithCatalog ? new LinearLayoutManager(this) : new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
mProductListRecyclerView.setAdapter(mAdapter);
break;
и изменение вида в onCreateViewHolder
, например:
@Override
public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(isViewWithCatalog ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null);
ProductRowHolder mh = new ProductRowHolder(v);
return mh;
}
От начала до конца вам нужно управлять переменной isViewWithCatalog, чтобы сначала отобразить макет.
Ответ 2
Я решил эту проблему, снова установив адаптер на RecyclerView
после изменения диспетчера компоновки.
listView.setLayoutManager(new LinearLayoutManager(this));
listView.setAdapter(adapter);
Ответ 3
В этом образцах SDK есть полный пример, однако он использует один файл макета для LayoutManagers
Для сохранения положения прокрутки при переключении макета они использовали эту функцию
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
// If a layout manager has already been set, get current scroll position.
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
}
switch (layoutManagerType) {
case GRID_LAYOUT_MANAGER:
mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
break;
case LINEAR_LAYOUT_MANAGER:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
break;
default:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
}
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
}
Ответ 4
Я думаю, что после прокрутки и изменения в режиме сетки первый элемент не воссоздается. Я решил это переопределить getItemViewType()
и раздуть файлы макета в onCreateViewHolder
соответственно.
Ответ 5
Я использую viewflipper и изменяю тип show list с анимацией. и красивый.
в главном xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ViewFlipper android:id="@+id/view_flipper"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v7.widget.RecyclerView
android:id="@+id/small_list" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" />
<android.support.v7.widget.RecyclerView android:scrollbarStyle="insideInset"
android:id="@+id/big_list" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" />
<android.support.v7.widget.RecyclerView android:scrollbarStyle="insideInset"
android:id="@+id/grid_list" android:paddingLeft="2.0dip" android:paddingRight="2.0dip" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" />
</ViewFlipper>
весь код в действии
private RecyclerView smallRecycleView;
private RecyclerView gridRecycleView;
private RecyclerView bigRecycleView;
private StaggeredGridLayoutManager gridLayoutManager;
private LinearLayoutManager bigLayoutManager;
private LinearLayoutManager smallLayoutManager;
private AAdapter adapterGrid;
private AAdapter adapterSmall;
private AAdapter adapterBig;
private ViewFlipper viewFlipper;
private TypeShow typeShowList = TypeShow.Small;
private AList list = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
setLayout( R.layout.main_layout);
super.onCreate(savedInstanceState);
try {
list = getItems(10);
viewFlipper = ((ViewFlipper)findViewById(R.id.view_flipper));
viewFlipper.setOutAnimation(MainActivity.this, R.anim.anim_fade_out_flip);
viewFlipper.setInAnimation(MainActivity.this, R.anim.anim_fade_in_flip);
smallRecycleView = ((RecyclerView)findViewById(R.id.small_list));
gridRecycleView = ((RecyclerView)findViewById(R.id.grid_list));
bigRecycleView = ((RecyclerView)findViewById(R.id.big_list));
smallRecycleView.setHasFixedSize(false);
gridRecycleView.setHasFixedSize(false);
bigRecycleView.setHasFixedSize(false);
smallLayoutManager = new LinearLayoutManager(MainActivity.this);
smallRecycleView.setLayoutManager(smallLayoutManager);
gridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
gridRecycleView.setLayoutManager(gridLayoutManager);
gridRecycleView.setItemAnimator(null);
bigLayoutManager = new LinearLayoutManager(MainActivity.this);
bigRecycleView.setLayoutManager(bigLayoutManager);
adapterSmall = new AAdapter(MainActivity.this,list,MainActivity.this,TypeShow.Small);
smallRecycleView.setAdapter(adapterSmall);
adapterGrid = new AAdapter(MainActivity.this,list,MainActivity.this,TypeShow.Grid);
gridRecycleView.setAdapter(adapterGrid);
adapterBig = new AAdapter(MainActivity.this,list,MainActivity.this,TypeShow.Big);
bigRecycleView.setAdapter(adapterBig);
if (Build.VERSION.SDK_INT >= 11)
{
smallRecycleView.setVerticalScrollbarPosition(1);
gridRecycleView.setVerticalScrollbarPosition(1);
bigRecycleView.setVerticalScrollbarPosition(1);
}
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.floating_action_button);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
smallRecycleView.setSelected(false);
bigRecycleView.setSelected(false);
gridRecycleView.setSelected(false);
viewFlipper.showNext();
if(typeShowList == TypeShow.Small){
typeShowList = TypeShow.Big;
fab.setImageResource(R.drawable.ic_type_grid);
}
else if(typeShowList == TypeShow.Big){
typeShowList = TypeShow.Grid;
fab.setImageResource(R.drawable.ic_atype_small);
}
else {
typeShowList = TypeShow.Small;
fab.setImageResource(R.drawable.ic_type_big);
}
}
});
fab.setImageResource(R.drawable.ic_type_big);
}
catch (Exception e){
}
}
type
public enum TypeShow {
Grid,
Small,
Big }
адаптер
public class AAdapter extends RecyclerView.Adapter<AAdapter.PersonViewHolder> {
private AList noteList = null;
private MainActivity mContext;
private TypeShow typeShow;
public AAdapter(MainActivity mContext, AList noteList, OnItemClickListener mListener, TypeShow typeShow){
this.noteList = noteList;
this.mContext= mContext;
this.mListener= mListener;
this.typeShow= typeShow;
}
@Override
public int getItemCount() {
return noteList.size();
}
@Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
if(typeShow == TypeShow.Grid) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_row_grid, viewGroup, false);
return new PersonViewHolder(v);
}
else if(typeShow == TypeShow.Small) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_row_small, viewGroup, false);
return new PersonViewHolder(v);
}
else {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_row_big, viewGroup, false);
return new PersonViewHolder(v);
}
}
@Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
PersonViewHolder(View itemView) {
super(itemView);
}
}
}
Ответ 6
Вы должны сделать два адаптера, каждый из которых реализует свой собственный oncreateviewholder, а затем использовать метод swapadapter для просмотра recycler для замены адаптеров.