如何在没有代码的情况下隐藏Android布局xml中的部分可见视图?

时间:2014-11-07 13:37:17

标签: android android-layout android-widget android-linearlayout android-appwidget

请在回答前完整阅读问题!

假设我有两个观点:

  1. first(黄色)在底部
  2. second(青色)填写first
  3. 上方视图的其余部分

    父视图的大小是动态的。

    当父高度动态设置为第一列中的值时,如何实现以下预期列UI?请注意部分可见视图是如何隐藏而不是裁剪的。

    What I want to achieve

    约束

    • 任何代码都不可能,我知道可以通过以下方式解决问题: second.setVisibility(second.getHeight() < SECONDS_PREFERRED_SIZE? GONE : VISIBLE) 但是我无权访问getHeight()所以解决方案必须是xml 只需通过RemoteViews编写UI状态即可轻松编写代码。
    • 基于上述不允许自定义视图甚至,只需基本布局管理器
      FrameLayoutLinearLayoutRelativeLayoutGridLayout
      或作为最后的手段之一:先进的: ViewFlipperListViewGridViewStackViewAdapterViewFlipper
    • layout_widthlayout_height 动态
      在示例中,我修复了它,因此很容易尝试不同的变体。上面的图像是layout_height更改为模拟我想要处理的可能性的显示值。
    • 我使用了TextView,但它通常适用于任何View
    • 细心观的人可能已经注意到上述内容限制了Home screen app widgets with RemoteViews的解决方案。

    尝试

    我尝试使用RelativeLayoutLinearLayout进行实施,但它们都表现为图片上的实际列。

    RelativeLayout的

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="64dp" (actually fill_parent, but fix it for sake of simplicity)
        android:layout_height="fill_parent" (first column on picture)
        android:layout_gravity="center"
        android:background="#666"
        tools:ignore="HardcodedText,RtlHardcoded"
        >
        <TextView
            android:id="@+id/first"
            android:layout_width="wrap_content"
            android:layout_height="16dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#8ff0"
            android:text="First"
            />
        <TextView
            android:id="@+id/second"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_above="@id/first"
            android:background="#80ff"
            android:text="Second"
            android:gravity="center"
            />
    </RelativeLayout>
    

    的LinearLayout

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="64dp" (actually fill_parent, but fix it for sake of simplicity)
        android:layout_height="fill_parent" (first column on picture)
        android:layout_gravity="center"
        android:background="#666"
        android:orientation="vertical"
        tools:ignore="HardcodedText,RtlHardcoded"
        >
        <TextView
            android:id="@+id/second"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#80ff"
            android:text="Second"
            android:gravity="center"
            />
        <TextView
            android:id="@+id/first"
            android:layout_width="wrap_content"
            android:layout_height="16dp"
            android:layout_gravity="right"
            android:background="#8ff0"
            android:text="First"
            />
    </LinearLayout>
    

2 个答案:

答案 0 :(得分:1)

如果这是RemoteViews / widget,请尝试使用多个布局文件。扩展AppWidgetProvider并覆盖onAppWidgetOptionsChanged方法。在此功能中,您将要执行以下操作:

Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);

然后在minHeight上确定哪种布局最适合膨胀。制作小部件时This page非常有用。

答案 1 :(得分:0)

虽然OPTION_APPWIDGET_MIN/MAX_WIDTH/HEIGHT并未真正报告实际值,但我找到了解决方法。 请注意,这并不能解决手头的问题,但这是一个相当复杂的解决方法。

想法的来源

Normal update from the widget host
26061-26061/net.twisterrob.app.debug V/TAG﹕ onReceive(Intent { act=android.appwidget.action.APPWIDGET_UPDATE flg=0x10000010 cmp=net.twisterrob.app.debug/net.twisterrob.app.AppWidgetProvider (has extras) } (Bundle[{appWidgetIds=[I@42b14090}]))  
26061-26061/net.twisterrob.app.debug V/TAG﹕ onUpdate([483])  

User tap with setOnClickPendingIntent
26061-26061/net.twisterrob.app.debug V/TAG﹕ onReceive(Intent { act=android.appwidget.action.APPWIDGET_UPDATE flg=0x10000010 cmp=net.twisterrob.app.debug/net.twisterrob.app.AppWidgetProvider bnds=[281,756][533,1071] (has extras) } (Bundle[{appWidgetIds=[I@42b14090}]))  
26061-26061/net.twisterrob.app.debug V/TAG﹕ onUpdate([483])

研究

RemoteViews.setOnClickPendingIntent广播用户点按时,它会the bounds of the view in the Intent。正如您在bnds=[281,756][533,1071]中看到的那样,视图为533-281=252宽且1071-756=315高,这些是像素,而Galaxy S4是XXHDPI (3x)设备,因此252x315 / 3 = 84x105正是我的经验观察是关于小部件单元大小的。

给定的界限取决于viewId的{​​{1}},因此要获得单元格大小,需要在布局中的根视图上附加待处理的意图。我的小部件有一个&#34;点击刷新&#34;我可以安全地附加到根布局的监听器。还有其他视图具有setOnClickPendingIntent s,但这些视图覆盖了根布局,因此它们的意图将被广播,就像常规的PendingIntent一样。

解决方案

现在,这意味着我们知道了确切的单元格大小,基于此可以计算出一些视图&#39;手工大小(更简单的布局)。基本上我们有办法获得 onClickListener ,我们可以&#34;硬编码&#34;将root.getHeight()的大小放入first,我们可以根据此计算是否显示R.dimen.firstHeightfirst或无。{/ p>

或者,像@AndrewOrobator建议一样使用这些边界:给适合大小的布局充气。

需要用户互动

唯一的问题是这需要用户互动至少一次。当窗口小部件主机发送更新时,没有边界,因此用户必须点击视图,以便我们具有该大小。我会解决这个问题,强迫用户点击视图一次(就在他们将小部件安装到家中之后):

second