- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 ListView
,其中的列表项具有背景资源。我想尽可能多地摆脱 overdraw 。我知道 Performance Case Study在 Romain Guy 的博客上发帖,但我无法完全优化 ListView 。简化示例的代码显示在本文底部。该示例基本上只是带有 ListView 的“新 Activity ”向导。我的问题基于此示例。这是初始未优化案例的带有和不带有 overdraw 标记的屏幕截图:
见证页面有灰色背景(在我的真实项目中是纹理),列表项有白色背景(在我的真实项目中是九色补丁)。 overdraw 是戏剧性的,屏幕的任何部分都被绘制一次,列表项在显示内容之前被绘制三次。
很容易去掉Window
中的decor view背景,切掉一层完整的overdraw。如果列表包含足够的项目来填满整个屏幕,我可以砍掉 ListView
背景并找到一个非常好的地方:
不幸的是,当列表中的项目少于填满整个屏幕时,这将不起作用。如果我不设置任何背景,则列表项下方没有任何内容。如果我在 ListView (或任何父级)上设置背景,我将对所有确实存在的列表项进行完全 overdraw :
这是次要的坏处,但令人不满意,因为大多数时候我的列表会跑出屏幕。有没有一种可靠的方法可以在 ListView 中的最后一项之后获得背景,而不引入 overdraw ?
Activity :
//MainActivity.java
public class MainActivity extends Activity {
private static final String[] DATA = { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet" };
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Optimization 1: getWindow().setBackgroundDrawableResource(android.R.color.transparent);
ListView lv = (ListView) findViewById(android.R.id.list);
lv.setAdapter(new ArrayAdapter<String>(this, R.layout.activity_main__list_item,
android.R.id.text1, data));
}
}
布局:
<!-- layout/activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#FFDDDDDD"
android:text="Page header information" />
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FFDDDDDD"
android:divider="@null" />
</LinearLayout>
<!-- layout/activity_main__list_item.xml -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@android:color/white" />
最佳答案
我自己想出了一个解决方案,避免了 j__m 的 answer 的嵌套权重问题。 .不利的一面是,它不能轻松地与其他 ListView 自定义组合。这可能比涉及 ListView 高度的 WRAP_CONTENT
的解决方案更有效,因为 ListView 在测量期间不必 getView(...)
其子项。
当然,ListView#onMeasure()
实现非常智能,一旦它有足够的高度来填充其父 View 并转到 getView()
无论如何,在 onDraw()
期间都是相同的位置,因此效率参数似乎没有实际意义。然而,Romain Guy 是 quite insistent ListView 不应使用 WRAP_CONTENT
。
/**
* A list view for use with list items that have their own background drawable. Such list views
* suffer from GPU Overdraw of the item background on top of the list view (ancestor) background.
* <p>
* This subclass detects when its data set contains enough elements to fill all available space
* and start scrolling. If this is the case, it sets its own background to transparent.
* </p>
* <p><strong>Limitation:</strong> Header and Footer views are ignored. If the list view has few
* enough items that it wouldn't scroll, but a header and/or footer are big enough to cause it to
* scroll anyway, the background is not hidden and overdraw is present.
* </p>
* <p>Source: https://stackoverflow.com/q/15625930/49489 CC-BY-SA</p>
*/
public class BackgroundListView extends ListView {
/** We need our own instance, because it's used as a sentinel value later on. */
private static final Drawable TRANSPARENT = new ColorDrawable(0x00000000);
/** If true, the next call to {@code onDraw(Canvas)} evaluates whether to show or hide the background. */
private boolean mNeedsBackgroundCheck = true;
/** The background to restore if the list shrinks. */
private Drawable mOriginalBackground;
public BackgroundListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public BackgroundListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BackgroundListView(Context context) {
this(context, null, 0);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
this.mOriginalBackground = this.getBackground();
}
@Override
public void setBackground(Drawable background) {
super.setBackground(background);
Drawable newBackground = getBackground();
if (newBackground != TRANSPARENT) {
this.mOriginalBackground = newBackground;
}
}
@Override
public void setBackgroundResource(int resid) {
super.setBackgroundResource(resid);
Drawable newBackground = getBackground();
if (newBackground != TRANSPARENT) {
this.mOriginalBackground = newBackground;
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mNeedsBackgroundCheck) {
maybeHideBackground();
}
super.onDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mNeedsBackgroundCheck = true;
};
@Override
protected void handleDataChanged() {
super.handleDataChanged();
mNeedsBackgroundCheck = true;
}
private void maybeHideBackground() {
if (isInEditMode()) {
return;
}
final int maxPosition = getAdapter().getCount() - 1;
final int firstVisiblePosition = getFirstVisiblePosition();
final int lastVisiblePosition = getLastVisiblePosition();
if (firstVisiblePosition > 0 || lastVisiblePosition < maxPosition) {
setBackground(TRANSPARENT);
} else {
setBackground(mOriginalBackground);
}
mNeedsBackgroundCheck = false;
}
}
关于android - 摆脱具有每个项目背景的 ListView 中的 overdraw ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15625930/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!