Android 强制gridview绘制所有平铺
我有一个android gridview,我正在使用一些自定义滚动,让它在两个维度上滚动-这意味着默认滚动不被调用 我怀疑这可能是屏幕外的行不可见的原因。我知道他们在那里,他们影响布局和一切,但他们从不画画 所以我的问题是,有没有办法强迫gridview在加载时绘制所有的分幅,而不仅仅是可见的分幅 谢谢 编辑:为了澄清-在我的TileDapter中,我将子计数精确设置为225。在我的gridview中,对getChildCount()的调用返回165 再次编辑:只有当gridview的高度大于屏幕的高度时才会发生这种情况-y轴上屏幕外的子项只需从childcount中减去-将子项的大小设置为一个数字,使其与屏幕上的所有子项紧密匹配即可消除问题,但会扼杀滚动的目的 密码 活动的XML布局:Android 强制gridview绘制所有平铺,android,android-gridview,Android,Android Gridview,我有一个android gridview,我正在使用一些自定义滚动,让它在两个维度上滚动-这意味着默认滚动不被调用 我怀疑这可能是屏幕外的行不可见的原因。我知道他们在那里,他们影响布局和一切,但他们从不画画 所以我的问题是,有没有办法强迫gridview在加载时绘制所有的分幅,而不仅仅是可见的分幅 谢谢 编辑:为了澄清-在我的TileDapter中,我将子计数精确设置为225。在我的gridview中,对getChildCount()的调用返回165 再次编辑:只有当gridview的高度大于屏
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:theme="@style/Theme.Custom"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="@+id/logmessage"
android:theme="@style/Theme.Custom"
android:layout_width="fill_parent"
android:layout_height="25dip"
android:text="LogMessage"/>
<RelativeLayout android:id="@+id/boardwrap"
android:layout_weight="1"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:gravity="center_vertical">
<com.MyProject.GameGrid
android:id="@+id/board"
android:theme="@style/Theme.Custom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="15"
android:stretchMode="none"
android:verticalSpacing="0dip"
android:horizontalSpacing="0dip"
android:padding="0dip"
android:columnWidth="20dip"
android:scrollbars="none"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/toolbar"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:background="#FFFFFFFF"/>
</LinearLayout>
游戏网格:
public GameGrid(Context context, AttributeSet attrs) {
super(context, attrs);
this.setNumColumns(15);
DisplayMetrics metrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
scale = metrics.density;
smallSize = Math.round(20 * scale);
largeSize = Math.round(40 * scale);
columnwidth = largeSize;
this.setColumnWidth(columnwidth);
Common.DebugMessage(Float.toString(columnwidth));
}
你可能会注意到我在这里定义了一个小尺寸和一个大尺寸——双击屏幕可以在两者之间切换
滚动(您之前帮助过我的内容)
安德烈亚斯
如果您的问题只是一个onDraw()
问题。在GridView
中,使用覆盖的Draw(canvas)
可以非常轻松地完成此操作。这有一个副作用,即在加载活动时增加处理器需求,但可以产生所需的效果。这种覆盖将如下所示:
//This may be used in your GridView or Activity -- whichever provides the best result.
public void draw(Canvas canvas)
{ int _num = myGridView.getChildCount();
for (int _i = _num; --_i >= 0; )
{ View _child = (View)myGridView.getChildAt(_i);
if (_child != null)
_child.draw(canvas);
}
}
附加技术(编辑)
有时重写draw()
会产生不利影响。我们真正想做的是在对象可用时触发对象进行绘制。以类似的方式重写invalidate()
通常会产生影响,具体取决于问题所在。由于我们已经确定,通过重写draw()
,我们会得到奇怪的结果,这似乎是下一步的行动
//This definitely goes in your GridView
public void invalidate()
{ int _num = myGridView.getChildCount();
for (int _i = _num; --_i >= 0; )
{ View _child = (View)myGridView.getChildAt(_i);
if (_child != null)
_child.invalidate();
}
}
必须理解的是,这种技术可能不会在您想要的时候强制绘制,而只是让操作系统知道它已经准备好在可用时重新绘制。由于无效不会自动向下层叠视图
树,因此如果图像视图
嵌套的深度比网格视图
更深,则必须进行调整。这可以与draw()
一起使用,也可以独立使用。此外,当与invalidate()
语句的适当位置一起使用时,可能会降低响应,但有助于保持图像的绘制
问题可能只是延迟布局或绘图问题。如果是这种情况,那么延迟加载解决方案可能是最好的。惰性加载程序是一种在需要时加载内容的方法,因此它通常使用较少的内存和处理,并在需要时显示所需内容。现在我不擅长延迟加载,因为我很少有这种需要。但在这里有一个很好的代码示例。它也是为GridView定制的
认为不适用(但可能对其他人有用)
我认为唯一的另一种问题可能是内存不足问题,它不会导致强制关闭(是的,它们确实存在)。这些都是特别难以捉摸和痛苦的照顾。在加载或滚动过程中,只有在LogCat中选择错误视图,才能发现这些错误。或者,您可以查看整个LogCat转储(我建议在您首先运行应用程序之前清除日志)
对于此类问题,了解图像的生命周期是如何工作的就变得非常重要。如果你的图像缩小到缩略图大小以便显示,我会考虑在全尺寸图像旁边制作真实的缩略图。因为在运行时临时收缩图像需要比保持原始大小更多的内存。由于这一切都发生在一个下降扫描,这可能是一个暂时的问题,表现出永久性。这将大大降低内存需求。(例如,2x2图像需要16个字节加上标题,而4x4图像需要64个字节加上标题[400%表示大小加倍!!])
此外,将System.gc()添加到代码中的关键位置将强制执行垃圾收集,从而更频繁地释放更多内存。(这并不能保证释放内存,但它的工作频率更高)
最好的解决方案可能是将这三者结合起来,但需要的信息比我们对这个问题的了解多一点。例如,我们需要查看您是否覆盖了
draw()
和onMeasure()
和onLayout()
以及其他一些细节。我提交了另一个答案,因为经过澄清,这个问题肯定与我最初认为的不同。但是,不应忘记前面答案中的技巧,它们是其他相关问题的重要资源,因此我将保留在这里
问题:
GridView现在绘制(有点),但是一遍又一遍地重复相同的图像,导致可怕的伪影。结果的工件非常糟糕,以至于不能很好地指示其他视图是否存在。这个问题实际上是由一个“透明度太高”的问题引起的
安卓和透明度
Android在处理透明度方面做得很好,它允许在当前视图下绘制对象,而顶视图处于焦点位置。然而,如果所有视图都是透明的,那么当Android需要刷新时,它就没有任何东西可以隐藏在所有视图后面。通常,这不是一个问题
通常,开发人员使用我们提供的工具,并尝试使用它们来实现一些整洁的事情。(耶!)
public TileAdapter(Context c) {
mContext = c;
}
@Override
public int getCount() {
return 225;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
int colWidth = ((GameGrid)parent).getColumnWidth();
if (convertView == null) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(colWidth , colWidth));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 0, 0, 0);
}
else {
imageView = (ImageView)convertView;
}
imageView.setImageResource(R.drawable.tile);
return imageView;
}
//This may be used in your GridView or Activity -- whichever provides the best result.
public void draw(Canvas canvas)
{ int _num = myGridView.getChildCount();
for (int _i = _num; --_i >= 0; )
{ View _child = (View)myGridView.getChildAt(_i);
if (_child != null)
_child.draw(canvas);
}
}
//This definitely goes in your GridView
public void invalidate()
{ int _num = myGridView.getChildCount();
for (int _i = _num; --_i >= 0; )
{ View _child = (View)myGridView.getChildAt(_i);
if (_child != null)
_child.invalidate();
}
}