为什么我不能将此运行时创建位图作为声明到片段中的 ImageView 的内容?

Why I can't put this runtime created Bitmap as content o an ImageView declared into a Fragment?

我绝对是 Android 开发新手,我正在开发我的第一个与 Udacity 初学者课程相关的教育应用程序。

应用程序的想法非常简单:它是一个烹饪食谱应用程序,其中使用从一个 recepy 切换到另一个交换在主 activity.

中向右或向左滑动。

所以这是我的 GitHub 与此应用程序相关的存储库:https://github.com/AndreaNobili/PastaFromRome

为了从一个 recepy 交换到另一个我使用了片段,所以基本上我有一个 activity_man.xml 文件,它只包含 header 和一个 viewpager对于片段:

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

然后我有 fragment_screen_slide_page.xml 表示与单个食谱相关的幻灯片,如下所示:

<!-- Dummy content. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="0dp">

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="fill_parent"
        android:scaleType="fitXY"
        android:layout_height="250dp" />
        <!--
        android:src="@drawable/carbonara"/>
        android:background="@drawable/carbonara" />
        -->

    <TextView android:id="@android:id/text1"
        style="@style/pastaTitleTextStyle" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="0px"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                style="@style/HeaderTextStyle"
                android:text="Difficoltà:" />


            <ImageView
                android:id="@+id/difficultyContainer"
                android:layout_width="fill_parent"
                android:scaleType="fitXY"
                android:layout_height="55dp" />

        </LinearLayout>


    </LinearLayout>

</LinearLayout>

此视图是一个片段,显示时包含当前配方。

它包含第一个 ImageView,其 ID imageView1 显示与当前食谱相关的图像,它工作正常。

然后它包含第二个 ImageView,其 ID difficultyContainer 是在运行时从应用程序创建的难度排名图像。这就是我要发疯的地方!!!

这是处理片段逻辑的 ScreenSlidePageFragment class(扩展 Fragment):

/**
 * A fragment representing a single step in a wizard. The fragment shows a dummy title indicating
 * the page number, along with some dummy text.
 *
 */
public class ScreenSlidePageFragment extends Fragment {

    private static final String TAG = "ScreenSlidePageFragment";
    /**
     * The argument key for the page number this fragment represents.
     */
    public static final String ARG_PAGE = "page";

    /**
     * The fragment's page number, which is set to the argument value for {@link #ARG_PAGE}.
     */
    private int mPageNumber;

    private static Context context;

    /**
     * Factory method for this fragment class. Constructs a new fragment for the given page number.
     */
    public static ScreenSlidePageFragment create(int pageNumber, Context baseContext) {
        ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, pageNumber);
        fragment.setArguments(args);

        context = baseContext;
        return fragment;
    }

    public ScreenSlidePageFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPageNumber = getArguments().getInt(ARG_PAGE);
    }

    /**
     * Method that will be called when the "pasta slider" is slided right or left
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

       System.out.println("PAGE NUMBER: "+ mPageNumber);

        // Obtain the colosseum_icon.png from the rsources as a Drawable:
        //Drawable drawable = getResources().getDrawable(R.drawable.colosseum_icon);

        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_screen_slide_page, container, false);
        ImageView imgSlideView = (ImageView) rootView.findViewById(R.id.imageView1);

        /* Retrieve the ImageView having id="difficultyContainer" (where to put the diifficulty
           image created):
         */
        //ImageView difficultyContainerImageView = (ImageView) rootView.findViewById(R.id.difficultyContainer);

        // Load the 2 images for the creation of the "difficulty graphic":
        Bitmap chefHatWhite = BitmapFactory.decodeResource(getResources(), R.drawable.chef_hat_white);
        Bitmap chefHatOk = BitmapFactory.decodeResource(getResources(), R.drawable.chef_hat_ok);

        // Where the previus image will be drawn:
        //Canvas canvas = new Canvas();
        Canvas difficultyCanvas = creaImgDifficulty();


        //switch (mPageNumber + 1) {
        switch (mPageNumber) {

            case 0:
                imgSlideView.setImageResource(R.drawable.carbonara);
                ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.carbonara));

                ImageView difficultyContainerImageView1 = (ImageView) rootView.findViewById(R.id.difficultyContainer);

                difficultyContainerImageView1.setImageDrawable(new BitmapDrawable(getResources(), ImgUtility.createRankingImg(context, 3)));

                break;

            case 1:
                imgSlideView.setImageResource(R.drawable.amatriciana);
                ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.amatriciana));



                break;

            case 2:
                imgSlideView.setImageResource(R.drawable.gricia_m);
                ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.gricia));


                break;

            case 3:
                imgSlideView.setImageResource(R.drawable.cacio_e_pepe);
                ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.cacio_e_pepe));


                break;

            case 4:
                imgSlideView.setImageResource(R.drawable.ajo_ojo_e_peperoncino);
                ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.ajo_ojo_peperoncino));


                break;
        }


        return rootView;
    }


    private void createImg(ImageView imgview) {
        Canvas canvas;

        Bitmap star = BitmapFactory.decodeResource(getResources(), R.drawable.star);
        Bitmap output = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(output);

        canvas.drawBitmap(star, star.getWidth() + 2, 0, null);

        imgview.setImageDrawable(new BitmapDrawable(getResources(), output));
    }

    private Canvas creaImgDifficulty() {
        Canvas canvas;
        Bitmap chefHatOk = BitmapFactory.decodeResource(getResources(), R.drawable.chef_hat_ok);
        Bitmap output = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(output);

        int space = 10; // the space between images

        for(int i = 0; i < 3; i++) {
            canvas.drawBitmap(chefHatOk, i * (chefHatOk.getWidth() + space), 0, null);
        }

        return canvas;
    }

    /**
     * Returns the page number represented by this fragment object.
     */
    public int getPageNumber() {
        return mPageNumber;
    }
}

所以基本上进入 onCreateView() 方法(我认为是在加载当前片段时执行的)我有 mPageNumber指定与特定配方相关的加载片段的变量,并且有一个 switch case 用于将此配方的特定信息加载到此片段中,例如:

案例 0: 这是第一个名为 carbonara 的食谱,所以它把 carbonara.png image (R.drawable.carbonara) into the previous ImageView havving id=imageView1 defined into the fragment_screen_slide_page.xml 文件。

它工作正常。

问题发生在我之前的代码中:

ImageView difficultyContainerImageView1 = (ImageView) rootView.findViewById(R.id.difficultyContainer);

difficultyContainerImageView1.setImageDrawable(new BitmapDrawable(getResources(), ImgUtility.createRankingImg(context, 3))); 

如您在代码中所见,difficultyContainerImageView1 标识具有 id=difficultyContainer[=75 的 ImageView =] 在我的片段中。这里我设置了一个由 ImgUtility.createRankingImg() 方法创建的图像。

public class ImgUtility {


    /**
     * Method that create the images related to the difficulty of a recepy
     * @param context
     * @param difficulty that represent the number of chef_hat_ok into the final image
     * @return a Bitmap representing the difficult of a recepy
     */
    public static Bitmap createRankingImg(Context context, int difficulty) {

        // Create a Bitmap image starting from the star.png into the "/res/drawable/" directory:
        Bitmap myBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.chef_hat_ok);


        // Create a new image bitmap having width to hold 5 star.png image:
        Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth() * 5, myBitmap.getHeight(), Bitmap.Config.RGB_565);

        Canvas tempCanvas = new Canvas(tempBitmap);

        // Draw the image bitmap into the cavas:
        tempCanvas.drawBitmap(myBitmap, 0, 0, null);
        tempCanvas.drawBitmap(myBitmap, myBitmap.getWidth(), 0, null);
        tempCanvas.drawBitmap(myBitmap, myBitmap.getWidth() * 2, 0, null);
        tempCanvas.drawBitmap(myBitmap, myBitmap.getWidth() * 3, 0, null);
        tempCanvas.drawBitmap(myBitmap, myBitmap.getWidth() * 4, 0, null);


        return tempBitmap;

    }


}

这种方法应该没问题,因为在我看来 return 一个位图,但是这张图片没有显示在具有 id 的片段 ImageView 中=难度容器

进入logcat我可以看到以下错误日志,但我不知道是否与我的问题有关:

08-21 19:38:12.315 4239-4925/com.example.android.pastafromrome W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (8730x1836, max=4096x4096)
08-21 19:38:12.335 4239-4925/com.example.android.pastafromrome W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (8730x1836, max=4096x4096)
08-21 19:38:12.335 4239-4925/com.example.android.pastafromrome W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (8730x1836, max=4096x4096)

为什么?我错过了什么?我该如何解决这个问题?如果您看到我的 GitHub 存储库并帮助我修复它,我将非常高兴。

问题是 Android 会自动调整 chef_hat_ok 到 1746px 宽度(我想这取决于设备)。看起来不错,但你做了 5 个,5 x 1746px 是 8370,纹理不能容纳它。

解决方案:禁用缩放或放置依赖于密度的资源(未选中该选项)。

禁用缩放。

ImgUtility.java

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap myBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.chef_hat_ok, options);

编辑:您需要将密度设置为 canvas tempCanvas.setDensity(myBitmap.getDensity());

Edit2:我还建议对难度容器进行一些更改

<ImageView
      android:id="@+id/difficultyContainer"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerInside"
      android:adjustViewBounds="true" />