【问题标题】:Problems vertically aligning a Button and horizontally oriented LinearLayout within a vertcally oriented LinearLayout在垂直方向的 LinearLayout 中垂直对齐 Button 和水平方向的 LinearLayout 时出现问题
【发布时间】:2010-07-12 06:33:18
【问题描述】:

我是用手机发帖的,所以请原谅愚蠢的拼写错误和格式问题。

我有一个活动,其中列出了玩家可以加载的已保存游戏。

我创建了一个定义 ScrollView 的简单布局 xml 文件。加载时,我抓取所有保存的游戏,并以编程方式将每个保存的游戏的视图添加到 ScrollView 的垂直方向 LinearLayout 子项。

每个游戏的视图由一个水平方向的 LinearLayout 组成,后者又包含一个 Button 和一个垂直方向的 LinearLayout。该 LinearLayout 又包含一些 TextViews 和 ImageViews(以及另外一个 LinearLayout,为了清楚起见,我在此省略)。

层次结构看起来像这样(省略了一些细节)。

 ScrollView
      LinearLayout - vertical 
           Each saved game:
           LinearLayout - horizontal 
                Button - load game
                LinearLayout - vertical 
                     TextView - game name
                     TextView - date string

我的问题:

我希望按钮的顶部和“游戏名称”texview 垂直对齐,但 TextView(或者它可能是 LinearLayout 父级)顶部有一些我无法摆脱的流氓填充。有关详细信息,请参阅屏幕截图。

LoadSaved 类: 注意: mScrollView 的名字很糟糕。它指的是 ScrollView 的子 LinearLayout。

   public class LoadSaved extends Activity {
     public LinearLayout mScrollView;
     private MinerDb mDb;

      public void onCreate(Bundle b) { 
             super.onCreate(b);
             setContentView(R.layout.loadsaved);
             mDb = new MinerDb(this);

            mScrollView = (LinearLayout) findViewById(R.id.load_scroll_view);
            Bundle[] savedGames = mDb.getSavedGames();

            for (int i = 0; i < savedGames.length; i++) {
                 Bundle game = savedGames[i];

                 final int gameId = game.getInt("gameId");
                 String name = game.getString("name");
                 String date = game.getString("date");

                 Bundle player = game.getBundle("player");
                 int playerMoney = player.getInt("money");
                 int playerHealth = player.getInt("health");

                 LinearLayout gameContainer = new LinearLayout(getApplicationContext());
                 gameContainer.setPadding(5, 5, 5, 5);
                 gameContainer.setGravity(Gravity.TOP);
                 gameContainer.setOrientation(LinearLayout.HORIZONTAL);
                 gameContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

                 Button loadButton = new Button(getApplicationContext());
                 loadButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                 loadButton.setText("Load");


                 LinearLayout gameInfo = new LinearLayout(getApplicationContext());
                 gameInfo.setOrientation(LinearLayout.VERTICAL);
                 gameInfo.setPadding(10,0,10,10);
                 gameInfo.setGravity(Gravity.TOP);
                 gameInfo.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

                 TextView nameView = new TextView(getApplicationContext());
                 nameView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
                 nameView.setGravity(Gravity.TOP);
                 nameView.setText(name);

                 TextView dateView = new TextView(getApplicationContext());
                 dateView.setPadding(5,0,0,0);
                 dateView.setGravity(Gravity.TOP);
                 dateView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
                 dateView.setText(date);

                 LinearLayout playerView = new LinearLayout(getApplicationContext());
                 playerView.setOrientation(LinearLayout.HORIZONTAL);
                 playerView.setPadding(5,0,0,0);
                 playerView.setGravity(Gravity.TOP);
                 playerView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

                 TextView playerMoneyView = new TextView(getApplicationContext());
                 playerMoneyView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                 playerMoneyView.setPadding(0,0,10,0);
                 playerMoneyView.setTextColor(Color.GREEN);
                 playerMoneyView.setText("$" + playerMoney);

                TextView playerHealthView = new TextView(getApplicationContext());
                playerHealthView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                playerHealthView.setPadding(0,0,10,0);
                playerHealthView.setTextColor(Color.RED);
                playerHealthView.setText(playerHealth + "%");

                playerView.addView(playerMoneyView);
                playerView.addView(playerHealthView);

                gameInfo.addView(nameView);
                gameInfo.addView(dateView);
                gameInfo.addView(playerView);

                gameContainer.addView(loadButton);
                gameContainer.addView(gameInfo);

                mScrollView.addView(gameContainer);

                loadButton.setOnClickListener(new OnClickListener() { 
                     public void onClick(View v) {
                           Log.e("LoadSaved", "LoadSaved::onCreate: Clicking: " + gameId);
                           Intent loadGameIntent = new Intent(LoadSaved.this, Miner.class);
                           loadGameIntent.putExtra("load_game", gameId);
                           startActivity(loadGameIntent);
                           finish();
                      }
                 });
            }
       }
  }

加载保存的.xml

           <LinearLayout
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:id="@+id/load_scroll_view" />

       </ScrollView>
  </LinearLayout>

【问题讨论】:

    标签: android user-interface vertical-alignment


    【解决方案1】:

    如果你想要任何一种对齐方式,为什么不使用RelativeLayout?这基本上旨在将一个视图与另一个视图对齐。 android:layout_alignTop 听起来像你想要的。

    (当然,还要验证所有控件中的填充值是否相同,但我相信你做到了。)

    【讨论】:

    • 谢谢。我会调查的。这是我的第一个 android 项目,所以我对这个平台有点菜鸟。
    • 是的,让布局按照你想要的方式工作一开始需要一些练习,但一旦你掌握了它,你就会喜欢它。对于超出简单元素列表的任何内容,RelativeLayout 通常是您的最佳选择。
    • 这看起来像我的解决方案。我现在正在酒吧里编写这个程序,所以可能需要一段时间来重写我的观点……啤酒正在造成损失。一旦我得到它,我会标记你是正确的。我想明天发布,所以我可能会等到发布后进行初始更新来解决这个问题。
    【解决方案2】:

    你为什么不尝试使用ListView 来实现那种 gui。

    您仍然需要定义行 xml。

    【讨论】:

      【解决方案3】:

      +1 建议 ListView 和 RelativeLayout 的答案。对于这种情况,您可能需要使用 RelativeLayout 的具有项目布局的 ListView。 (如果有很多项目,ListView 会更好地扩展,如果这是一个已保存游戏的列表,它似乎会增长很多。)对于这种类型的 UI,建议让整个行/列表项目可点击而不是而不是使用小的加载按钮,但这是一个设计问题,最终取决于您。

      不要使用getApplicationContext 创建视图。 Activity 是一个上下文,在你的情况下只需传递this

      默认情况下,LinearLayouts 会尝试通过其文本基线对齐子视图(如果存在)。请注意,按钮的加载文本底部与屏幕截图中的 CURRENT_GAME 文本完全对齐。试试gameContainer.setBaselineAligned(false)

      通常,如果您设置了baselineAlignedChildIndex,您的gameInfo 布局只会报告其中一个子级的基线,但在以编程方式创建LinearLayouts 时,这种行为似乎在cupcake 和eclair 之间发生了变化。 (链接到在 AOSP here 中更改它的提交。)

      【讨论】:

      • Re: 传递“this”作为上下文。似乎当我这样做时,我最终会到处泄漏内存。然后在开始一些活动后它崩溃了。使用 getApplicationContext 内存消耗保持稳定。
      • 所有答案都很好(我很高兴我学到了一些关于 RelativeLayout 的知识),但你的答案最简单。谢谢。
      • 您确实必须小心将 Activity 作为上下文传递的位置,但使用它来构造视图应该没有问题,除非您以这样的方式存储对这些视图的引用坚持超出您的活动的生命周期。如果您这样做,您可能会遇到其他问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-12
      • 1970-01-01
      • 2014-10-08
      • 2017-02-22
      • 2014-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多