Android:GridLayout 大小和 View.GONE 行为
Android: GridLayout size and View.GONE behaviour
我想做一个GridLayout
,当其中一个children的Visibility
设置为GONE
时,它被下一个[=27=取代].
这不是我自己画的作业,以便更好地解释。
我可以让布局在列数和宽度等方面正常工作。 GridLayout
的默认 GONE
行为使 child 只是消失而不是被替换,就好像它一开始就不存在一样,就像其他布局一样。
我确实尝试了很多东西,我尝试搜索 SO 和 google,但我似乎无法解决这个问题。这将是我正在使用的应用程序最方便的布局 on.Is 无论如何都可以在布局中执行此操作而无需以编程方式执行此操作?或者两者的组合?
解决方案是将 RecyclerView 与 GridLayoutManager 一起使用。关键是使用 notifyItemRemoved 通知适配器有关已删除项的更改。 RecyclerViews 中有很多自定义空间,例如消失项目的漂亮动画、屏幕上剩余项目的重新排列、项目装饰等。您可以根据需要应用所有这些自定义和附加逻辑来删除项目,以满足您的特定需求问题。
Activity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> dataSet = getSampleDataSet();
recyclerView = (RecyclerView) findViewById(R.id.grid);
recyclerView.setAdapter(new MyAdapter(dataSet));
recyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(), 2));
}
private List<String> getSampleDataSet() {
List strings = new ArrayList();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
strings.add("five");
strings.add("six");
return strings;
}
}
适配器
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
List<String> dataSet;
public MyAdapter(List<String> dataSet) {
this.dataSet = dataSet;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView tileView = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(tileView);
return myViewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.view.setText(dataSet.get(position));
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dataSet.remove(position);
notifyItemRemoved(position); // this notifies the adapter about item being removed
}
});
}
@Override
public int getItemCount() {
return dataSet.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView view;
public MyViewHolder(TextView itemView) {
super(itemView);
view = itemView;
}
}
Activity布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
网格项
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridItem"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:textColor="@android:color/white"
android:gravity="center"
android:text="Tile"/>
结果
前:
点击4后,在真机上,你会看到这个动作的漂亮的框架动画
解决与以下相同的问题:
package ua.vsgroup.widgets;
import android.content.Context;
import android.support.v7.widget.GridLayout;
import android.util.AttributeSet;
import android.view.View;
public class vsGridLayout extends GridLayout {
View[] mChild = null;
public vsGridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public vsGridLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public vsGridLayout(Context context) {
this(context, null);
}
private void arrangeElements() {
mChild = new View[getChildCount()];
for (int i = 0; i < getChildCount(); i++) {
mChild[i] = getChildAt(i);
}
removeAllViews();
for (int i = 0; i < mChild.length; i++) {
if (mChild[i].getVisibility() != GONE)
addView(mChild[i]);
}
for (int i = 0; i < mChild.length; i++) {
if (mChild[i].getVisibility() == GONE)
addView(mChild[i]);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
arrangeElements();
super.onLayout(changed, left, top, right, bottom);
}
}
如果您不需要再次将视图变为可见,您可以通过从 GridLayout 中删除视图来解决它。
private void hideView(View view) {
GridLayout gridLayout = (GridLayout) view.getParent();
for (int i = 0; i < gridLayout.getChildCount(); i++) {
if (view == gridLayout.getChildAt(i)) {
gridLayout.removeViewAt(i);
break;
}
}
}
基于 答案。谢谢大佬
创建您的自定义 GridLayout 小部件。
package com.isolpro.pricelist.custom;
public class RearrangingGridLayout extends GridLayout {
private final List<View> views = new ArrayList<>();
public RearrangingGridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RearrangingGridLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RearrangingGridLayout(Context context) {
this(context, null);
}
private void arrangeElements() {
removeAllViews();
for (int i = 0; i < views.size(); i++) {
if (views.get(i).getVisibility() != GONE)
addView(views.get(i));
}
}
public void saveViews() {
for (int i = 0; i < getChildCount(); i++) {
views.add(getChildAt(i));
}
}
public void hideViewAtIndex(int index) {
if (index >= 0 && index < views.size()) {
views.get(index).setVisibility(GONE);
arrangeElements();
}
}
public void showViewAtIndex(int index) {
if (index >= 0 && index < views.size()) {
views.get(index).setVisibility(VISIBLE);
arrangeElements();
}
}
}
使用方法如下:
保存GridLayout绑定(渲染)后的所有children,使用如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
RearrangingGridLayout rglPrices = findViewById(R.id.rglPrices);
rglPrices.saveViews();
}
现在,隐藏你的观点
rglPrices.hideViewAtIndex(indexOfView);
同样,表达你的看法
rglPrices.showViewAtIndex(indexOfView);
大功告成!
对于我的项目,必须保留 children 的位置,所以我使用了 index.html 。通过更新显示和隐藏函数,您可以轻松修改代码以使用视图 ID 等其他内容。
我想做一个GridLayout
,当其中一个children的Visibility
设置为GONE
时,它被下一个[=27=取代].
这不是我自己画的作业,以便更好地解释。
我可以让布局在列数和宽度等方面正常工作。 GridLayout
的默认 GONE
行为使 child 只是消失而不是被替换,就好像它一开始就不存在一样,就像其他布局一样。
我确实尝试了很多东西,我尝试搜索 SO 和 google,但我似乎无法解决这个问题。这将是我正在使用的应用程序最方便的布局 on.Is 无论如何都可以在布局中执行此操作而无需以编程方式执行此操作?或者两者的组合?
解决方案是将 RecyclerView 与 GridLayoutManager 一起使用。关键是使用 notifyItemRemoved 通知适配器有关已删除项的更改。 RecyclerViews 中有很多自定义空间,例如消失项目的漂亮动画、屏幕上剩余项目的重新排列、项目装饰等。您可以根据需要应用所有这些自定义和附加逻辑来删除项目,以满足您的特定需求问题。
Activity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> dataSet = getSampleDataSet();
recyclerView = (RecyclerView) findViewById(R.id.grid);
recyclerView.setAdapter(new MyAdapter(dataSet));
recyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(), 2));
}
private List<String> getSampleDataSet() {
List strings = new ArrayList();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
strings.add("five");
strings.add("six");
return strings;
}
}
适配器
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
List<String> dataSet;
public MyAdapter(List<String> dataSet) {
this.dataSet = dataSet;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView tileView = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(tileView);
return myViewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.view.setText(dataSet.get(position));
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dataSet.remove(position);
notifyItemRemoved(position); // this notifies the adapter about item being removed
}
});
}
@Override
public int getItemCount() {
return dataSet.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView view;
public MyViewHolder(TextView itemView) {
super(itemView);
view = itemView;
}
}
Activity布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
网格项
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridItem"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:textColor="@android:color/white"
android:gravity="center"
android:text="Tile"/>
结果
前:
点击4后,在真机上,你会看到这个动作的漂亮的框架动画
解决与以下相同的问题:
package ua.vsgroup.widgets;
import android.content.Context;
import android.support.v7.widget.GridLayout;
import android.util.AttributeSet;
import android.view.View;
public class vsGridLayout extends GridLayout {
View[] mChild = null;
public vsGridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public vsGridLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public vsGridLayout(Context context) {
this(context, null);
}
private void arrangeElements() {
mChild = new View[getChildCount()];
for (int i = 0; i < getChildCount(); i++) {
mChild[i] = getChildAt(i);
}
removeAllViews();
for (int i = 0; i < mChild.length; i++) {
if (mChild[i].getVisibility() != GONE)
addView(mChild[i]);
}
for (int i = 0; i < mChild.length; i++) {
if (mChild[i].getVisibility() == GONE)
addView(mChild[i]);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
arrangeElements();
super.onLayout(changed, left, top, right, bottom);
}
}
如果您不需要再次将视图变为可见,您可以通过从 GridLayout 中删除视图来解决它。
private void hideView(View view) {
GridLayout gridLayout = (GridLayout) view.getParent();
for (int i = 0; i < gridLayout.getChildCount(); i++) {
if (view == gridLayout.getChildAt(i)) {
gridLayout.removeViewAt(i);
break;
}
}
}
基于
创建您的自定义 GridLayout 小部件。
package com.isolpro.pricelist.custom;
public class RearrangingGridLayout extends GridLayout {
private final List<View> views = new ArrayList<>();
public RearrangingGridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RearrangingGridLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RearrangingGridLayout(Context context) {
this(context, null);
}
private void arrangeElements() {
removeAllViews();
for (int i = 0; i < views.size(); i++) {
if (views.get(i).getVisibility() != GONE)
addView(views.get(i));
}
}
public void saveViews() {
for (int i = 0; i < getChildCount(); i++) {
views.add(getChildAt(i));
}
}
public void hideViewAtIndex(int index) {
if (index >= 0 && index < views.size()) {
views.get(index).setVisibility(GONE);
arrangeElements();
}
}
public void showViewAtIndex(int index) {
if (index >= 0 && index < views.size()) {
views.get(index).setVisibility(VISIBLE);
arrangeElements();
}
}
}
使用方法如下:
保存GridLayout绑定(渲染)后的所有children,使用如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
RearrangingGridLayout rglPrices = findViewById(R.id.rglPrices);
rglPrices.saveViews();
}
现在,隐藏你的观点
rglPrices.hideViewAtIndex(indexOfView);
同样,表达你的看法
rglPrices.showViewAtIndex(indexOfView);
大功告成!
对于我的项目,必须保留 children 的位置,所以我使用了 index.html 。通过更新显示和隐藏函数,您可以轻松修改代码以使用视图 ID 等其他内容。