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

如何在没有代码的情况下隐藏Android布局xml中部分可见的视图?,android,android-layout,android-widget,android-linearlayout,android-appwidget,Android,Android Layout,Android Widget,Android Linearlayout,Android Appwidget,回答前请仔细阅读问题 假设我有两种观点: 底部第一个(黄色) second(青色)填充上面的视图的其余部分first 父视图的大小是动态的 当父级高度动态设置为第一列中的值时,如何实现下面预期的列UI?请注意,部分可见的视图是如何隐藏而不是裁剪的 约束条件 任何代码都不可能,我知道可以通过以下方法解决问题: second.setVisibility(second.getHeight()

回答前请仔细阅读问题

假设我有两种观点:

  • 底部第一个
    (黄色)
  • second
    (青色)填充上面的视图的其余部分
    first
  • 父视图的大小是动态的

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

    约束条件
    • 任何代码都不可能,我知道可以通过以下方法解决问题:
      second.setVisibility(second.getHeight()
      但是我没有访问
      getHeight()
      的权限,因此解决方案必须是纯xml。
      可以通过
      remoteview
      轻松地只编写UI状态代码
    • 基于上述不允许自定义视图t甚至,只允许基本布局管理器
      框架布局
      线性布局
      相对布局
      网格布局

      或者作为最后手段,选择一种高级方法:
      ViewFlipper
      ListView
      GridView
      StackView
      AdapterViewFlipper
    • layout\u宽度
      layout\u高度
      是动态的

      在本例中,我修复了它,因此很容易尝试不同的变体。上图是
      layout\u height
      更改为显示值,模拟我想要处理的可能性
    • 我使用了
      TextView
      ,但它通常适用于任何
      视图
    • 有观察力的人可能已经注意到,上述限制了解决问题的方法
    尝试 我尝试使用
    RelativeLayout
    LinearLayout
    实现,但它们都表现为图片上的实际列

    相对布局
    
    
    线性布局
    如果这是RemoteView/widget,请尝试使用多个布局文件。扩展并重写该方法。在此函数中,您需要执行以下操作:

    Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
    int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
    
    然后以最小高度为例,确定哪种布局最适合充气。在制作小部件时非常有用。

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

    想法的来源 调查 当用户广播点击时,它将。正如您在
    bnds=[281756][5331071]
    中看到的,视图是
    533-281=252
    宽和
    1071-756=315
    高,这些是像素,Galaxy S4是一个设备,因此
    252x315/3=84x105
    这正是我对小部件单元大小的经验观察

    给定的边界取决于给定给
    setOnClickPendingContent
    viewId
    ,因此要获得单元格大小,需要在布局中的根视图上附加挂起的意图。我的小部件有一个“点击刷新”监听器,我可以安全地将它附加到根布局。还有一些视图确实有
    pendingent
    s,但是这些视图覆盖了根布局,因此它们的意图将被广播,就像常规的
    onClickListener
    s一样

    解决方案 现在,这意味着我们知道确切的单元大小,基于此,可以手动计算某些视图的大小(对于更简单的布局)。本质上,我们有办法获得
    根.getHeight()
    ,我们可以将
    第一个
    的大小“硬编码”为
    R.dimen.firstHeight
    ,并由此计算是否显示
    第一个
    第二个

    或者,像@AndrewOrobator建议的那样,利用这些边界:为适合大小的布局充气

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


    “我没有访问getHeight()的权限”为什么?@mmlooloo:因为上没有
    View
    getter。远程进程(窗口小部件主机)没有反馈,这是一种方式,这就是为什么我只要求布局xml。它的16加-24表示顶部边缘的填充为8。@danny117我不确定我是否理解,请复制我的一次尝试来测试它。然后进行您建议的更改,并通过将
    layout\u height=“16dp”
    更改为图像上的值来比较视觉效果。很明显,顶部边缘有填充物,填充物是如何消失的?我也对这个谜题的答案感兴趣。对于这种类型的问题,多个布局文件是个好主意。我的目标是API 10,这种方法就是API 16。即使我在新版本中使用它,我想我也无法获得正确的单元格大小。我知道三星Galaxy S4有
    84dp x 105dp
    widget单元,但我无法接近这个数字。我想它给了我我在
    上指定的
    最小高度。我将再次尝试这些最小值/最大值并报告。我再次检查(所有值都是
    dp
    ):“OnAppWidgetOptionChanged(appWidgetID,Bundle[{appWidgetMaxHeight=89,appWidgetCategory=1,appWidgetMaxWidth=89,appWidgetMinHeight=68,appWidgetMinWidth=68}])
    68x68
    -
    89x89
    84x105
    相去甚远。是的,小部件就是这样。它们给出的大小是近似的,甚至在不同的设备或发射器之间都不稳定。
    <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>
    
    Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
    int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_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])
    
    @Override
    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction())) {
            for (int appWidgetId : getAppWidgetIds(intent)) {
                Rect storedBounds = getSizeFromPreferences(appWidgetId);
                Rect sourceBounds = intent.getSourceBounds();
                if (storedBounds == null && sourceBounds != null) {
                    // no stored size, but we just received one, save it
                    setSizeToPreferences(appWidgetId, sourceBounds);
                    storedBounds = sourceBounds;
                }
                if (storedBounds == null) {
                    // we didn't have a stored size, neither received one
                    // force the user to interact with the widget once so we have a size
                    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_tap_to_refresh);
                    views.setOnClickPendingIntent(R.id.root, createRefresh(context, appWidgetId));
                    AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, views);
                } else {
                    // update as usual, and use the bounds from getSizeFromPreferences(appWidgetId)
                    onUpdate(context, AppWidgetManager.getInstance(context), new int[] {appWidgetId});
                }
            }
        } else {
            super.onReceive(context, intent);
        }
    }
    private @NonNull int[] getAppWidgetIds(Intent intent) {
        int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
        if (appWidgetIds == null) {
            appWidgetIds = new int[0];
        }
        return appWidgetIds;
    }
    private @NonNull PendingIntent createRefresh(Context context, int appWidgetId) {
        Intent intent = new Intent(context, MyAppWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetId);
        return PendingIntent.getBroadcast(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }