https://developer.android.com/about/versions/android-4.3.html#UI中引入的光学边界功能似乎为父布局添加了额外的填充设置。 在下面的屏幕截图中,可以看到3个示例片段:
片段#2在根布局中有一个额外的填充。我的目标是删除那个填充,以便我可以放置& TextView完全基于它的内部光学边界来布局。
如何删除第二个片段创建的内部填充?我已经尝试将填充设置为0dp或" -11dp"但这不是我希望做的。
感谢您的任何建议。
代码:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingTop="20dp">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@drawable/shadow_with_stroke_gray"
android:text="lorem ipsum etc"
android:padding="20dp"
/>
</FrameLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutMode="opticalBounds"
android:paddingLeft="20dp"
android:paddingTop="20dp">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@drawable/shadow_with_stroke_gray"
android:text="lorem ipsum etc"
android:padding="20dp"
/>
</FrameLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutMode="opticalBounds"
android:paddingLeft="20dp"
android:paddingTop="20dp">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#ffffcc"
android:text="lorem ipsum etc"
android:padding="20dp"
/>
</FrameLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="40dp">
<fragment
android:id="@+id/fragment1"
android:layout_width="312dp"
android:layout_height="match_parent"
class="opticalboundstest.WithoutOpticalBoundsFragment"/>
<Space
android:layout_width="21dp"
android:layout_height="match_parent"/>
<fragment
android:id="@+id/fragment2"
android:layout_width="312dp"
android:layout_height="match_parent"
class="opticalboundstest.WithOpticalBoundsFragment"/>
<Space
android:layout_width="21dp"
android:layout_height="match_parent"/>
<fragment
android:id="@+id/fragment3"
android:layout_width="312dp"
android:layout_height="match_parent"
class="opticalboundstest.WithWorkingOpticalBoundsFragment"/>
</LinearLayout>
正在使用的阴影图片:
答案 0 :(得分:0)
片段#2在根布局中有一个额外的填充
实际上,它不是填充。蓝线和红线之间的间隙称为光学边界(或光学插入物)。 Here你可以看到:
所有布局元素也尊重其子视图的光学边界,根据其中视图的光学边界调整自己的边界。
查看ViewGroup中的computeOpticalInsets()
Insets computeOpticalInsets() {
if (isLayoutModeOptical()) {
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
for (int i = 0; i < mChildrenCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == VISIBLE) {
Insets insets = child.getOpticalInsets();
left = Math.max(left, insets.left);
top = Math.max(top, insets.top);
right = Math.max(right, insets.right);
bottom = Math.max(bottom, insets.bottom);
}
}
return Insets.of(left, top, right, bottom);
} else {
return Insets.NONE;
}
}
因此,父母的光学界限是他孩子最大的光学范围。
我的目标是删除那个填充,以便我可以放置&amp;完全基于它的内部光学边界来布局TextView。
您不能完全基于它的内部光学边界放置TextView,因为它的父级可以有其他具有光学边界的子级。 你为什么想要消除这个差距?它对用户不可见
答案 1 :(得分:0)
一种可能的方法是使用Java反射完全禁用Insets。
/**
* Helper class for the optical bounds layout mode.
*/
public class Bounds {
private static final String TAG = Bounds.class.getName();
/**
* Disables insets for a given {@link android.view.View} or {@link android.view.ViewGroup}.
* This method should be called during the construction phase of the <code>target</code> object.
*
* @param target Target object to disable the layout insets.
* @return Whether the operation succeeded.
*/
public static boolean disableLayoutInsets(final View target) {
try {
final Field mLayoutInsets = View.class.getDeclaredField("mLayoutInsets");
mLayoutInsets.setAccessible(true);
final Class c = Class.forName("android.graphics.Insets");
final Field f = c.getDeclaredField("NONE");
mLayoutInsets.set(target, f.get(target));
} catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException e) {
Log.e(TAG, "Exception", e);
return false;
}
return true;
}
}