SeekBar进度更新重绘整个ViewGroup

时间:2013-09-02 21:20:53

标签: android android-layout android-fragments

我有一个视图模板,其中包含用于片段的主RelativeLayout和2 FrameLayouts。(我附加了一个图像以显示我的模板。)红色是RelativeLayout,棕色和绿色是FrameLayouts

现在,棕色部分包含一个非常沉重但很漂亮的网格列表。绿色部分包含一个简单的LinearLayout Image(灰色),Seekbar(蓝色)和TextView(粉红色)。

每1秒在UI线程上更新SeekBar进度。我注意到网格列表的滚动冻结了1秒钟。通过做一些traceview调试,我注意到列表每1秒重新绘制一次。

最重要的是,我在Developers菜单中启用了实际设备上的“Show layout updates”选项。它显示了更有趣的观点 - Seekbar之上的所有内容都被重新绘制。为什么SeekBar视图更新重绘上面的所有视图?

我无法显示很多代码,但是我做标准片段附件,然后在片段中创建一个具有特定睡眠周期的线程,然后在ui-thread上更新搜索栏进度。

如果您需要更多信息,请告诉我,我会尝试更新该帖子。今天我花了4-5个小时试图理解它为什么这样做 - 没有成功......

主模板非常简单。类似的东西:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bgwood"
android:orientation="vertical" >


<FrameLayout
android:id="@+id/top_container"
android:layout_width="match_parent"
android:layout_height="match_parent" 
android:layout_above="@+id/bottom_container" />



<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff111111" />

</RelativeLayout>

enter image description here

编辑:更多信息......

底部片段(绿色)包含类似以下视图结构:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/player_playercontainer"
    android:layout_width="fill_parent"
    android:layout_height="115dp"
    android:layout_gravity="bottom"
    android:background="@drawable/bg_player"
    android:gravity="center"
    android:baselineAligned="false"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center|center_vertical"
        android:background="#000000"
        android:scaleType="fitXY"
        android:src="@drawable/hdd" />


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:layout_weight="0.64"
        android:gravity="center"
        android:orientation="vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingRight="5dp"
            android:shadowColor="#cc111111"
            android:shadowDx="1"
            android:shadowDy="1"
            android:shadowRadius="1"
            android:text="unknown"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="#888"
            android:textSize="13dp" />


        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:max="100" />


    </LinearLayout>



</LinearLayout>

将片段附加到底部布局:

if (bundle == null) {
        FragmentTransaction fragmentTransaction = mManager.beginTransaction();  
        SourceListFragment fragment = BottomFragment();
        fragmentTransaction.add(R.id.bottom_container, fragment).commit();
} 

更新片段中的搜索栏:

/* Called every 1 sec */
void updateCallback(final int progress) {

    getActivity().runOnUiThread(new Runnable() {
        public void run() {
        if (seekBarView == null) {
            seekBarView = (SeekBar) view.findViewById(R.id.progressBar);
        } 
        seekBarView.setProgress()
    });

}

3 个答案:

答案 0 :(得分:1)

  

我无法显示很多代码,但我会做标准片段附件   然后在具有特定睡眠周期的片段中创建一个线程   然后在ui-thread上更新搜索栏进度。

尝试使用Handler更新ProgressBar

定义以下全局变量:

Handler updateHandler;

// loop control variable
boolean shouldStop;

Runnable updateRunnable;

初始化变量:

updateHandler = new Handler();

shouldStop = false;

updateRunnable = new Runnable() {

    @Override
    public void run() {
        if (!shouldStop) {

            // Post this Runnable again with a delay of 1000 milliseconds
            updateHandler.postDelayed(this, 1000L);

            // Update ProgressBar
            updateCallback(Your_Progress_Value);
        }
    }
};

// Start the update process
updateHandler.post(updateRunnable);

在这种情况下,您无需指定运行更新的线程:

/* Called every 1 sec */
void updateCallback(final int progress) {
    if (seekBarView == null) {
        seekBarView = (SeekBar) view.findElementById(R.id.progressBar);
    } 
    seekBarView.setProgress(...);
}

当您需要结束更新过程时,将使用boolean变量shouldStop。将其设置为true,更新将停止。

注意:您的布局中有一个ProgressBar窗口小部件,而您的代码使用SeekBar。你能在帖子中做出更正吗?另一件事,findElementById(int)中没有签名View的方法。这是您的实际代码吗?

答案 1 :(得分:1)

问题是TextView宽度设置为wrap_content,因此每次更新值时都会重绘它。问题是如果重新绘制子元素,即TextView,那么所有父视图也将强制重绘。

基本上,将动态视图设置为特定大小或match_parent。

答案 2 :(得分:0)

我想我看到它正在做什么,通过使用android:layout_above您的顶部片段是在底部之后绘制的。所以它受到更新的底部影响。

使用android:layout_alignParentTop="true"可以防止这种情况发生。

如果你还没有看到它,你一定要查看I/O talk about custom views。 RelativeLayouts可能是一个噩梦,但他们在解释他们的工作方式方面表现非常出色。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bgwood"
android:orientation="vertical" >


<FrameLayout
android:id="@+id/top_container"
android:layout_width="match_parent"
android:layout_height="match_parent" 
android:layout_alignParentTop="true"
android:layout_marginBottom="300dp"  />



<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff111111"
android:layout_alignParentBottom="true" />

</RelativeLayout>