如何以编程方式在 Android 中的按钮中缩放或自动调整可绘制顶部的图像?

How can I scale or auto fit the image of a Drawable Top in a Button in Android programatically?

我正在开发一个应用程序,我在其中加载了 GridView 中的多个按钮。

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:paddingLeft="25dp"
      android:paddingRight="25dp"
      android:paddingTop="5dp"
      android:paddingBottom="5dp"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:orientation="vertical">
    <GridView
        android:id="@+id/gridview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:columnWidth="128dp"
        android:numColumns="auto_fit"
        android:verticalSpacing="5dp"
        android:horizontalSpacing="5dp"
        android:stretchMode="columnWidth"
        android:gravity="center" />
  </LinearLayout>

按钮是使用适配器动态添加的,但如果我预定义边界 (320x320) 在某些设备中看起来很棒,但在其他设备中太小或太大,我无法按我的意愿缩放或自动调整图像如果我选择内在边界,它们总是微型的。

预定义边界 (320x320):

智能手机视图:

平板电脑视图:

内部边界 (136x136):

我将图像存储在 Assets 目录中,您的第一个问题是为什么?

你可以告诉我应该将它们保存在 Resources/drawable 中,我知道这一点,但我有 100 多张图片,每张图片它们存储在具有唯一 ID 的子文件夹中,其中可以包含至少一张具有如下 ID 的图像:1.jpg、2.jpg 等

如您所见,如果我将所有这些图像和子目录移动到可绘制文件夹,它就无法工作 (Can the Android drawable directory contain subdirectories?)。

为了从 Assets 文件夹中获取 Drawable,我有这个功能:

public Drawable GetImage(int ID)
{
    var thumbnail = string.Format("Thumbnails/{0}/1.jpg", ID);
    using (StreamReader sr = new StreamReader(Application.Context.Assets.Open(thumbnail)))
    {
        Drawable d = Drawable.CreateFromStream(sr.BaseStream, null);

        d.SetBounds(0, 0, 320, 320);

        return d;
    }
}

以下是我如何将适配器中的数据加载到按钮:

btnRecipe.Text = data[position].name;
btnRecipe.SetHeight(560);
//            btnRecipe.SetWidth(122);
// btnRecipe.SetCompoundDrawablesWithIntrinsicBounds();
btnRecipe.SetTextColor(new Android.Graphics.Color(255, 255, 255));
btnRecipe.SetCompoundDrawables(null, data[position].image, null, null);

我想知道是否有任何方法可以处理或自动调整图像,因为我有另一个例子,使用 Drawable 文件夹中的数据和 XML 代码,图像被缩放而没有任何其他示例:

代码:

<Button
    android:text="@string/BtnComidas"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/my_white"
    android:id="@+id/BtnComidas"
    android:drawableTop="@drawable/comidas" />

另外,我想澄清一下,这张图片比之前的图片 (136x136) 小了 128x128,而且看起来好多了,而且我在 Drawable 文件夹中只有一张图片,我不知道没有 hdpi 或 mdpi 副本,正如您所见,它在智能手机和平板电脑上看起来很棒,我不需要做任何额外的更改来缩放它。

一个可能的问题和答案,为什么我要使用 GridView 来加载按钮?例如,如果我应该使用另一个控件或布局。

我不知道还有什么方法可以同时显示图像和文本,但我能够按预期处理点击事件。

此外,如果有人有其他方法可以在 GridView 中显示带有文本的多个图像或其他可以解决我当前问题的方法,我愿意接受任何建议。感谢您的帮助、时间、经验和有价值的知识。

我找到了可以帮助更多人的解决方案:

1) 您需要将 GridView 的列宽共享给构造函数:

GridDishes.Adapter = new GridViewAdapter(this, data, GridDishes.ColumnWidth, IsSmartphone());

2) 然后你配置理想的尺寸:

public GridViewAdapter(Context c, List<CompatedInfo> data, int size, bool isSmartphone)
{
    NotifyDataSetChanged();
    context = c;
    this.data = data;

    //Define the size that you're going to use
    if (Size > 0)
        Size = (int)(size * 0.8);

    //This is going to help you to have the same size for all elements
    if (isSmartphone)
        Height = (int)(Size * 1.65);
    else
        Height = (int)(Size * 1.7);
}

3) 在适配器中定义新尺寸:

data[position].image.SetBounds(0, 0, Size, Size);

4) 如果你希望所有的视图具有相同的高度,高度在构造函数中预定义:

btnRecipe.SetHeight(Height);

可选:

如果你想确定屏幕并像我对元素的最大尺寸做的那样做一些小的改变,这个函数很有用:

private bool IsSmartphone()
{
    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager.DefaultDisplay.GetMetrics(metrics);

    float yInches = metrics.HeightPixels / metrics.Ydpi;
    float xInches = metrics.WidthPixels / metrics.Xdpi;
    double diagonalInches = Math.Sqrt(xInches * xInches + yInches * yInches);

    if (diagonalInches >= 6.5)
    {
        return false;
    }
    else
    {
        return true;
    }
}

函数来源: