- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一个 Android 应用程序,其中的 Activity 在 ScrollView 中显示内容。内容顶部有一个用于显示图像的占位符。该图像是从 Internet 下载的,可能需要几秒钟才能显示。图像占位符最初是空的。下载图像后,它会动态添加到占位符中。
最初我遇到了以下问题。
为了解决这个问题,我添加了代码,以便在将 ImageView 添加到占位符后调整滚动位置。这样做的问题是,在显示图像和调整 ScrollView 过程中, ScrollView 会出现闪烁。原因是scrollBy 函数是从可运行对象中调用的。在可运行对象之外调用scrollBy不会导致闪烁,但滚动位置不正确 - 原因是 ScrollView 上的项目没有足够的时间来重新计算/测量其尺寸/高度。
这是一个示例应用程序,说明了这个问题:
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollview);
startImageDownload();
simulateImageScroll();
}
private void simulateImageScroll() {
// scroll to the bottom of the scroll view
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
}
});
}
private void startImageDownload() {
Handler handler = new Handler(getMainLooper());
// simulate a delay for the image download to illustrate the flashing problem in the scrollview
handler.postDelayed(new Runnable() {
@Override
public void run() {
displayImage("");
}
}, 2000);
}
// when the image is downloaded we add it to the image container
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
adjustScrolling(container);
}
private void adjustScrolling(RelativeLayout container) {
// adjust scroll if the image is loaded before the current content
if (scrollView.getScrollY() > container.getTop()) {
container.measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
final int amountToScroll = container.getMeasuredHeight();
// the following does not cause flickering but scrolls to the wrong position
//scrollView.scrollBy(0, amountToScroll);
// adjust the scrollview so that it keeps the current view unchanged
scrollView.post(new Runnable() {
@Override
public void run() {
// this causes flickering but scrolls to the correct position
scrollView.scrollBy(0, amountToScroll);
}
});
}
}
}
这是布局文件:
<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/imageContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
关于如何解决这个问题有什么想法吗?
最佳答案
编辑:目前,您的布局正在闪烁,因为添加蓝色 View 会导致重绘布局(和滚动)。所以滚动发生了一次,接下来你滚动到你想要的位置。这是第二次搬家。
要解决这个问题,你需要知道android是如何绘制view的。 https://developer.android.com/guide/topics/ui/how-android-draws.html
简单来说,onMeasure()
- onLayout()
- onDraw()
。您还可以通过 ViewTreeObserver().addOnGlobalLayoutListener()
在 onLayout()
和 onDraw()
之间添加布局代码。
https://developer.android.com/reference/android/view/ViewTreeObserver.OnGlobalLayoutListener.html
ps:我还是推荐使用漂亮可爱的图片库,Picasso。
固定代码是:在调用draw()
之前设置滚动。这样,您只能绘制一次。
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
int amountToScroll = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollview);
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
scrollView.scrollBy(0, amountToScroll);
amountToScroll = 0;
}
});
startImageDownload();
simulateImageScroll();
}
private void simulateImageScroll() {
// scroll to the bottom of the scroll view
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
}
});
}
private void startImageDownload() {
Handler handler = new Handler(getMainLooper());
// simulate a delay for the image download to illustrate the flashing problem in the scrollview
handler.postDelayed(new Runnable() {
@Override
public void run() {
displayImage("");
}
}, 2000);
}
// when the image is downloaded we add it to the image container
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
adjustScrolling(container);
}
private void adjustScrolling(RelativeLayout container) {
// adjust scroll if the image is loaded before the current content
if (scrollView.getScrollY() > container.getTop()) {
container.measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
amountToScroll = container.getMeasuredHeight();
}
}
}
<小时/>
我强烈建议使用Picasso。 http://square.github.io/picasso/
这一行将解决您的所有问题。
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
您可以将本地镜像文件或网络图像(url)加载到您的imageView中。
在您的情况下,删除 startImageDownload()
和 simulateImageScroll()
,并在 onResume()
上调用 displayImage()
。
修复了displayImage():
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
Picasso.with(this).load(imageFilename).into(img);
adjustScrolling(container);
}
或者,如果您出于学术原因想直接解决这个问题,
不要调整滚动条。看来使用 scrollBy
来解决您的问题并不是真正的解决方案。真正的原因是导致 UI 重绘的代码。可能正在调用 invalidate()
或类似的东西。
以编程方式添加 ImageView 不是一个好主意。因为您的RecyclerView或ListView的ViewHolder无法重用 View ,因此会导致性能下降。如果你能避免它,那就这样做。 (例如,使用 xml)
看来将 ImageView 添加到 imageContainer 是真正的问题。 imageContainer 有 android:layout_height="wrap_content"
属性,这意味着它没有固定的高度,它取决于它自己的子容器。尝试更改为固定值,例如:android:layout_height="500dp"
关于java - 膨胀 View 并调用scrollBy时 ScrollView 闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47224536/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!