英文:
How to get the position of a view relative to its parent including padding?
问题
我有一个FrameLayout,其中包含一个LinearLayout子视图。我通过将其底部内边距设置为100来更新LinearLayout的位置。但是当我收到OnLayoutChange回调时,bottom
和oldBottom
的值是相同的。
我尝试过offsetDescendantRectToMyCoords
、getLocationInWindow
和getGlobalVisibleRect
,但似乎都没有考虑到内边距。
以下是我的布局文件:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/frameLayout">
</FrameLayout>
banner_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/banner_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom">
<LinearLayout
android:id="@+id/banner_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/banner_bgcolor">
<TextView
android:id="@+id/banner_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:padding="2dp"
android:textSize="15sp"
android:textColor="#FF323232"
android:textColorLink="#FF828282"
android:textIsSelectable="false"
android:textStyle="normal"
android:layout_weight="1"
android:layout_gravity="left"
android:text="Banner text here"/>
<TextView
android:id="@+id/banner_logotext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingBottom="2dp"
android:paddingTop="2dp"
android:paddingRight="10dp"
android:textSize="15sp"
android:textColor="#FF828282"
android:textColorLink="#FF828282"
android:textIsSelectable="false"
android:textStyle="normal"
android:layout_gravity="right"
android:text="Logo"/>
</LinearLayout>
</LinearLayout>
还有我的主Activity:
class MainActivity : AppCompatActivity() {
var bottom = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val frameLayout = findViewById<FrameLayout>(R.id.frameLayout)
val bannerView = frameLayout.addBannerView()
frameLayout.setOnClickListener {
bannerView.post {
bottom += 32
bannerView.setPadding(0, 0, 0, bottom)
}
}
}
private fun FrameLayout.addBannerView(): View {
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.banner_layout, this, true)
val bannerView = findViewById<View>(R.id.banner_layout)
bannerView.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
val msg = "Difference bottom: ${bottom - oldBottom}\n" +
"Position top left: (${bannerView.left}, ${bannerView.top})"
Log.e("MainActivity", msg)
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
}
return bannerView
}
}
基本上,上面的代码在onCreate
中将bannerView
添加到frameLayout
,并在点击时将32dp添加到bannerView
的底部内边距。然而,无论我如何滑动视图,得到的输出始终是这样的:
Difference bottom: 0
Position top left: (0, 0)
英文:
I have a FrameLayout with a LinearLayout child. I am updating the position of the LinearLayout by setting its bottom padding to 100. However when I get the OnLayoutChange callback, the bottom
and oldBottom
are identical.
I have tried offsetDescendantRectToMyCoords
, getLocationInWindow
, and getGlobalVisibleRect
but it doesn't seem like any of these take into account padding.
Here is are my layout files:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/frameLayout">
</FrameLayout>
banner_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/banner_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom">
<LinearLayout
android:id="@+id/banner_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/banner_bgcolor">
<TextView
android:id="@+id/banner_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:padding="2dp"
android:textSize="15sp"
android:textColor="#FF323232"
android:textColorLink="#FF828282"
android:textIsSelectable="false"
android:textStyle="normal"
android:layout_weight="1"
android:layout_gravity="left"
android:text="Banner text here"/>
<TextView
android:id="@+id/banner_logotext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingBottom="2dp"
android:paddingTop="2dp"
android:paddingRight="10dp"
android:textSize="15sp"
android:textColor="#FF828282"
android:textColorLink="#FF828282"
android:textIsSelectable="false"
android:textStyle="normal"
android:layout_gravity="right"
android:text="Logo"/>
</LinearLayout>
</LinearLayout>
And my main activity:
class MainActivity : AppCompatActivity() {
var bottom = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val frameLayout = findViewById<FrameLayout>(R.id.frameLayout)
val bannerView = frameLayout.addBannerView()
frameLayout.setOnClickListener {
bannerView.post {
bottom += 32
bannerView.setPadding(0,0,0, bottom)
}
}
}
private fun FrameLayout.addBannerView(): View {
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.banner_layout, this, true)
val bannerView = findViewById<View>(R.id.banner_layout)
bannerView.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
val msg = "Difference bottom: ${bottom - oldBottom}\n" +
"Position top left: (${bannerView.left}, ${bannerView.top})"
Log.e("MainActivity", msg)
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
}
return bannerView
}
}
Basically, the above code adds the bannerView
to the frameLayout
in onCreate
, and adds an onClick that adds 32dp to the bottom padding of the bannerView
. The output I get is always like this, even though I can see the view moving up the screen.
Difference bottom: 0
Position top left: (0, 0)
答案1
得分: 1
不使用代码,很难理解发生了什么。请尝试分享代码。
但是,听起来你正在尝试通过调整内部子视图的填充来更新 FrameLayout 中的位置,但在 OnLayoutChange 回调中无法获得更新后的位置信息。
可能的一个问题是,OnLayoutChange 回调可能会在填充更改生效之前被调用。这可能是因为填充更改没有立即生效,而是在下一次布局过程中排队等待应用。
为了确保填充更改在调用 OnLayoutChange 回调之前生效,你可以尝试使用 View.post() 方法来安排填充更改在当前布局过程完成后应用。例如,你可以像这样做:
myLinearLayout.post(new Runnable() {
@Override
public void run() {
myLinearLayout.setPadding(0, 0, 0, 100);
}
});
这将确保填充更改在下一次布局过程中应用,这应该确保 OnLayoutChange 回调可以访问到更新后的位置信息。
英文:
Without code, it's hard to understand what is happening. Please, try to share the code.
But, it sounds like you are trying to update the position of a child view within a FrameLayout by adjusting its padding, but you are having trouble getting the updated position information from the OnLayoutChange callback.
One possible issue is that the OnLayoutChange callback may be called before the padding changes take effect. This could be because the padding changes are not being applied immediately, but rather are being queued up to be applied during the next layout pass.
To ensure that the padding changes are applied before the OnLayoutChange callback is called, you can try using the View.post() method to schedule the padding changes to be applied after the current layout pass has completed. For example, you could do something like this:
myLinearLayout.post(new Runnable() {
@Override
public void run() {
myLinearLayout.setPadding(0, 0, 0, 100);
}
});
This will ensure that the padding changes are applied during the next layout pass, which should ensure that the OnLayoutChange callback has access to the updated position information.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论