Android 方向更改时的ImageView-Drawable忽略收进并返回原始状态 编辑3:
出于历史原因,我保留以下原始问题。但是,我发现问题并不是孤立于Android 方向更改时的ImageView-Drawable忽略收进并返回原始状态 编辑3:,android,screen-orientation,android-imageview,invalidation,android-framelayout,Android,Screen Orientation,Android Imageview,Invalidation,Android Framelayout,出于历史原因,我保留以下原始问题。但是,我发现问题并不是孤立于FrameLayout。因此,更新了标题 我创建了一个示例项目来演示这个问题,而不是用更多的代码来挤满这篇文章;它在谷歌项目托管上 该问题的摘要如下: 可绘制的纵向方向,在其上设置了特定边界,在 更改方向并返回到纵向,不会保留 设定界限。相反,它会恢复到其原始边界。这是在 尽管强制设置了方向变化的明确界限。 请注意,您稍后在单击等时设置的任何边界都将得到遵守 我还有一份报告,其中包含两项单独的活动来说明这一问题 简单的普通活动正好说明
FrameLayout
。因此,更新了标题
我创建了一个示例项目来演示这个问题,而不是用更多的代码来挤满这篇文章;它在谷歌项目托管上
该问题的摘要如下:
可绘制的纵向方向,在其上设置了特定边界,在
更改方向并返回到纵向,不会保留
设定界限。相反,它会恢复到其原始边界。这是在
尽管强制设置了方向变化的明确界限。
请注意,您稍后在单击等时设置的任何边界都将得到遵守
我还有一份报告,其中包含两项单独的活动来说明这一问题
ImageView
上使用自定义BitmapDrawable
的活动-此活动在边界更改时打印到日志中onBoundsChange()
中也没有遵守这些边界
原始问题: 我使用了一个
FrameLayout
,其中两个ImageView
s堆叠在一起,用于显示“电池状态”图形。这是纵向模式。在横向模式下,我显示不同的布局(图表)
我的问题是,假设电池状态显示为30%。现在,我旋转屏幕并显示图表。当我回到纵向时,电池图形会回到其原始位置(即“满”)
我尝试了各种各样的方法,试图弄清楚到底发生了什么。调试表明,“顶部”图形的边界确实按照预期设置。所以这似乎是一个无效的问题。我正在介绍2个类和2个布局XML(都是简化的)的代码,这有助于重现问题。同时附加用于ImageView的占位符PNG
有人能发现错误吗?要重新创建问题,请运行应用程序,然后单击“更新”按钮。图形将“填充”到某个级别。然后,切换到横向,然后返回到纵向。该图形不记得其早期值
活动:
public class RotateActivity extends Activity {
private View portraitView, landscapeView;
private LayoutInflater li;
private Configuration mConfig;
private ValueIndicator indicator;
private Button btn;
private Random random = new java.util.Random();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
li = LayoutInflater.from(this);
portraitView = li.inflate(R.layout.portrait, null);
landscapeView = li.inflate(R.layout.landscape, null);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mConfig = newConfig;
initialize();
}
@Override
protected void onResume() {
mConfig = getResources().getConfiguration();
initialize();
super.onResume();
}
private void initialize(){
if(mConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
displayLandscape();
} else {
displayPortrait();
}
}
private void displayLandscape() {
setContentView(landscapeView);
}
private void displayPortrait() {
setContentView(portraitView);
btn = (Button)portraitView.findViewById(R.id.button1);
indicator = (ValueIndicator)portraitView.findViewById(R.id.valueIndicator1);
/*
* Forcing the graphic to perform redraw to its known state when we return to portrait view.
*/
indicator.updateIndicatorUi();
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
updateIndicator(random.nextInt(100));
}
});
}
private void updateIndicator(int newValue){
indicator.setPercent(newValue);
}
}
trait.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.gs.kiran.trial.inval.ValueIndicator
android:id="@+id/valueIndicator1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update" />
</LinearLayout>
indicator.xml(自定义视图中使用的FrameLayout的xml)
landscape.xml(虚拟占位符-足以重新创建问题)
AndroidManifest.xml代码段:
<activity
android:label="@string/app_name"
android:name=".RotateActivity"
android:configChanges="orientation|keyboardHidden">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
编辑 我还尝试调用了
setPercent()
,并在displaystraphicview()
中传递了一个保存的值,这基本上是在我们回到纵向模式时强制更新到已知状态。还是不走运。请注意,日志告诉我可提取项的边界是正确的。我不明白为什么无效判决没有发生
编辑2:
mPercent
它始终存储最后一个已知的百分比值setPercent()
code以更新成员变量mPercent
;然后调用updateIndicateUi()
方法updateIndicatorUi()
(现在是一种public
方法)现在使用状态(即mPercent
)来执行其工作updateIndicatorUi()
。这将强制电池图形自我更新我们的想法是,每当我们从横向模式返回到纵向模式时,强制重新绘制并使其无效。再一次-我确实看到电池“内容”可绘制的界限被设置为所需,但UI拒绝跟上进度。只是猜测,但在旋转活动中,请尝试更改超级调用的顺序:
super.onConfigurationChanged(newConfig); // super called before initialize()
mConfig = newConfig;
initialize();
我已经在Google代码宿主上检查了您的代码(感谢您如此彻底地记录代码的努力),我发现当您从横向返回到纵向时,可绘制文件上设置的边界确实再次发生了变化 绘图表上的边界不是由您的代码更改的,而是由
ImageView
的布局方法更改的。放置新布局(setContentView
)时,将运行所有布局代码,包括ImageView
ImageView
更改其包含的可绘制边界,这就是为什么您将可绘制边界更改为原始边界的原因
导致绑定更改的堆栈跟踪是:
Thread [<1> main] (Suspended (entry into method onBoundsChange in BitmapDrawable))
BitmapDrawable.onBoundsChange(Rect) line: 293
BitmapDrawable(Drawable).setBounds(int, int, int, int) line: 131
ImageView.configureBounds() line: 769
ImageView.setFrame(int, int, int, int) line: 742
ImageView(View).layout(int, int, int, int) line: 7186
LinearLayout.setChildFrame(View, int, int, int, int) line: 1254
LinearLayout.layoutVertical() line: 1130
LinearLayout.onLayout(boolean, int, int, int, int) line: 1047
LinearLayout(View).layout(int, int, int, int) line: 7192
FrameLayout.onLayout(boolean, int, int, int, int) line: 338
FrameLayout(View).layout(int, int, int, int) line: 7192
LinearLayout.setChildFrame(View, int, int, int, int) line: 1254
LinearLayout.layoutVertical() line: 1130
LinearLayout.onLayout(boolean, int, int, int, int) line: 1047
LinearLayout(View).layout(int, int, int, int) line: 7192
PhoneWindow$DecorView(FrameLayout).onLayout(boolean, int, int, int, int) line: 338
PhoneWindow$DecorView(View).layout(int, int, int, int) line: 7192
ViewRoot.performTraversals() line: 1145
ViewRoot.handleMessage(Message) line: 1865
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 130
ActivityThread.main(String[]) line: 3835
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 507
ZygoteInit$MethodAndArgsCaller.run() line: 847
ZygoteInit.main(String[]) line: 605
NativeStart.main(String[]) line: not available [native method]
Thread[main](挂起(在BitmapDrawable中进入方法onBoundsChange))
BitmapDrawable.onBoundsChange(Rect)行:293
BitmapDrawable(Drawable).setBounds(int,int,int,int)行:131
ImageView.configureBounds()行:769
设置帧(int,int,int,int)行:742
图像视图(视图)。布局(int,int,int,int)行:7186
setChildFrame(视图,int,int,int,int)行:1254
LinearLayout.layoutVertical()行:1130
线性布局。仅布局(布尔,int,int,int,int)行:1047
线性布局(视图)。布局(int,int,int,int)线:7192
FrameLayout.onLayout(boolean,int,int,int,int)行:338
框架布局(视图)。布局(int,int,int,int)行:7192
setChildFrame(视图,int,int,int,int)行:1254
LinearLayout.layoutVertical()行:1130
线性布局。仅布局(布尔,int,int,int,int)行:1047
线性布局(视图)。布局(int,int,int,int)线:7192
PhoneWindow$DecorView(框架布局)。仅布局(布尔值,int,int,int,
<activity
android:label="@string/app_name"
android:name=".RotateActivity"
android:configChanges="orientation|keyboardHidden">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
super.onConfigurationChanged(newConfig); // super called before initialize()
mConfig = newConfig;
initialize();
Thread [<1> main] (Suspended (entry into method onBoundsChange in BitmapDrawable))
BitmapDrawable.onBoundsChange(Rect) line: 293
BitmapDrawable(Drawable).setBounds(int, int, int, int) line: 131
ImageView.configureBounds() line: 769
ImageView.setFrame(int, int, int, int) line: 742
ImageView(View).layout(int, int, int, int) line: 7186
LinearLayout.setChildFrame(View, int, int, int, int) line: 1254
LinearLayout.layoutVertical() line: 1130
LinearLayout.onLayout(boolean, int, int, int, int) line: 1047
LinearLayout(View).layout(int, int, int, int) line: 7192
FrameLayout.onLayout(boolean, int, int, int, int) line: 338
FrameLayout(View).layout(int, int, int, int) line: 7192
LinearLayout.setChildFrame(View, int, int, int, int) line: 1254
LinearLayout.layoutVertical() line: 1130
LinearLayout.onLayout(boolean, int, int, int, int) line: 1047
LinearLayout(View).layout(int, int, int, int) line: 7192
PhoneWindow$DecorView(FrameLayout).onLayout(boolean, int, int, int, int) line: 338
PhoneWindow$DecorView(View).layout(int, int, int, int) line: 7192
ViewRoot.performTraversals() line: 1145
ViewRoot.handleMessage(Message) line: 1865
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 130
ActivityThread.main(String[]) line: 3835
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 507
ZygoteInit$MethodAndArgsCaller.run() line: 847
ZygoteInit.main(String[]) line: 605
NativeStart.main(String[]) line: not available [native method]