Android RecyclerView:将布局文件 LIST 更改为 GRID onOptionItemSelected
Android RecyclerView: Change layout file LIST to 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
布局从 List
更改为 Grid
以及 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
布局:
不知道为什么滚动后会这样。有没有其他方法可以像这样改变视图。
Today i just saw that this problem is because of ImageView
, without it working perfectly.
请帮忙,你的帮助将不胜感激。
我找到了 activity 开头的解决方案 我设置了 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 变量以首先显示哪个布局。
我通过在更改布局管理器后再次将适配器设置为 RecyclerView
解决了这个问题。
listView.setLayoutManager(new LinearLayoutManager(this));
listView.setAdapter(adapter);
我认为在滚动并改回网格视图后,不会重新创建第一项。我通过覆盖 getItemViewType()
并相应地在 onCreateViewHolder
中扩充布局文件来解决这个问题。
在这个 SDK samples 中有一个完整的示例,但是它为两个 LayoutManager 使用一个布局文件
为了在切换布局时保持滚动位置,他们使用了这个功能
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);
}
我正在开发一个 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
布局从 List
更改为 Grid
以及 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
布局:
不知道为什么滚动后会这样。有没有其他方法可以像这样改变视图。
Today i just saw that this problem is because of
ImageView
, without it working perfectly.
请帮忙,你的帮助将不胜感激。
我找到了 activity 开头的解决方案 我设置了 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 变量以首先显示哪个布局。
我通过在更改布局管理器后再次将适配器设置为 RecyclerView
解决了这个问题。
listView.setLayoutManager(new LinearLayoutManager(this));
listView.setAdapter(adapter);
我认为在滚动并改回网格视图后,不会重新创建第一项。我通过覆盖 getItemViewType()
并相应地在 onCreateViewHolder
中扩充布局文件来解决这个问题。
在这个 SDK samples 中有一个完整的示例,但是它为两个 LayoutManager 使用一个布局文件
为了在切换布局时保持滚动位置,他们使用了这个功能
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);
}