有时ImageView中的图片不显示

Sometimes the image in the ImageView does not show

在 Activity 上有 4 个视图,用户可以在其中 "bet" 根据当前答案上的当前金额来 "bet" 问题的正确答案图像随着金额的变化而变化(从一无所有到一包钱到一堆钱)

有时当值被添加到视图中时(通过 touch/click 或从另一个答案中拖动它)图像不显示(只有当该答案之前没有任何钱时才会发生这种情况).

这是查看代码(我在其中添加了一些日志和注释):

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class SuperMoneyView extends LinearLayout
{
    protected TextView _moneyValueTextView;
    protected ImageView _moneyPacktView;
    protected long _value = 1000000;
    private Activity _activity;
    protected boolean _isSoundActive = false;

    public SuperMoneyView(Context context)
    {
        this(context, null);
    }

    public SuperMoneyView(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public SuperMoneyView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        initConfig(true);
    }

    public SuperMoneyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
        initConfig(true);
    }

    public void initConfig(boolean setDefaultValues)
    {
        setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
    }

    public void setActivity(Activity activity)
    {
        _activity = activity;
    }

    public View getMoneyValueView()
    {
        return _moneyValueTextView;
    }

    public void setImage(final Drawable drawable)
    {
        Log.e("AnswerView", "setImage");
        if(drawable == null)
        {
            Log.e("AnswerView", "setImage -- Drawable Null");
            _moneyPacktView.setVisibility(View.INVISIBLE);
            return;
        }
        else
        {
            Log.e("AnswerView", "setImage -- Drawable Not Null");
            _moneyPacktView.setVisibility(View.VISIBLE);
        }

        if(_moneyPacktView != null)
        {//This part is executed but the image does not show
            Log.e("AnswerView", "setImage -- Real set image");
            _moneyPacktView.setImageDrawable(drawable);
            _moneyPacktView.setAlpha(1.0f);
            _moneyPacktView.setVisibility(View.VISIBLE);
            invalidate();
        }
    }

    public ImageView getMoneyImageView()
    {
        return _moneyPacktView;
    }

    public boolean isSoundActive()
    {
        return _isSoundActive;
    }
    public void setSoundActive(boolean active)
    {
        _isSoundActive = active;
    }

    public long getValue()
    {
        return _value;
    }
    public void setValue(long value)
    {
        setValue(value, _value);
    }
    public void setValue(long value, long oldValue)
    {
        final boolean playSound = value > oldValue;
        _value = value;

        if(_activity == null)
        {//This part is never executed (Activity is always different than null)
            Log.e("AnswerView", "SetValue no Activity");
            realSetValue(playSound);
        }
        else
        {
            try
            {
                _activity.runOnUiThread(//I tried this, because I thought that maybe it wasn't running on the UI Thread
                        new Runnable()
                        {
                            @Override
                            public void run()
                            {
                                realSetValue(playSound);
                            }
                        }
                );
                Log.e("AnswerView", "SetValue Activity");
            }
            catch(Exception e)
            {//Never called either
                e.printStackTrace();
                Log.e("AnswerView", "SetValue Catch");
                realSetValue(playSound);
            }
        }
    }
    private void realSetValue(boolean sound)
    {
        Log.e("AnswerView", "RealSetValue");
        if(_moneyValueTextView != null)
        {
            Log.e("AnswerView", "_moneyValueTextView != null");
            if(sound && isSoundActive())
            {
                Log.e("AnswerView", "Sound Active");
                MediaUtils.playMoneyDrag();
            }
            _moneyValueTextView.setText("" + _value);
        }
        if(_moneyPacktView != null)
        {//Always different than null
            Log.e("AnswerView", "_moneyPacktView != null");
            setImage(getImageForAmount(_value));
        }
    }

    public void updateValue(long toAdd)
    {
        long oldValue = _value;

        _value += toAdd;
        if(_value < 0l)
        {
            _value = 0l;
        }
        setValue(_value, oldValue);
    }

    public void setWrong()
    {
        if(getValue() > 0)
        {
            RemoveMoneyAnimation animation = new RemoveMoneyAnimation(_moneyPacktView);
            animation.setDuration(1000);
            startAnimation(animation);
        }
    }

    private Drawable getImageForAmount(long amount)
    {
        if(amount == 0)
        {
            Log.e("AnswerView", "getImageForAmount -- amount == 0 -- Null");
            return null;
        }
        else if(amount <= 50000)
        {
            Log.e("AnswerView", "getImageForAmount -- icn_money_pack_bet_single");
            return getContext().getResources().getDrawable(R.drawable.icn_money_pack_bet_single);
        }
        else if(amount <= 150000)
        {
            Log.e("AnswerView", "getImageForAmount -- icn_money_pack_bet_medium");
            return getContext().getResources().getDrawable(R.drawable.icn_money_pack_bet_medium);
        }
        else if(amount <= 500000)
        {
            Log.e("AnswerView", "getImageForAmount -- icn_money_pack_bet_full");
            return getContext().getResources().getDrawable(R.drawable.icn_money_pack_bet_full);
        }
        else if(amount <= 1000000)
        {
            Log.e("AnswerView", "getImageForAmount -- icn_money_pack_bet_extra_full");
            return getContext().getResources().getDrawable(R.drawable.icn_money_pack_bet_extra_full);
        }
        Log.e("AnswerView", "getImageForAmount -- Null");
        return null;
    }

    protected class RemoveMoneyAnimation extends Animation implements Animation.AnimationListener
    {
        final View _view;
        final float _initialWidth;
        final float _initialHeight;

        public RemoveMoneyAnimation(View view)
        {
            _view = view;
            _initialWidth = _view.getWidth();
            _initialHeight = _view.getHeight();

            setAnimationListener(this);
        }

        public void restoreViewSize()
        {
            _view.getLayoutParams().width = (int)_initialWidth;
            _view.getLayoutParams().height = (int)_initialHeight;
            _view.setLayoutParams(_view.getLayoutParams());
            _view.setRotation(0.0f);
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t)
        {
            try
            {
                if(interpolatedTime > 0.5f)
                {
                    _view.setAlpha(1.0f + (-1.0f * (interpolatedTime - 0.5f) * 2.0f));
                }
                _view.getLayoutParams().width = (int)(_initialWidth - (_initialWidth * interpolatedTime));
                _view.getLayoutParams().height = (int)(_initialHeight - (_initialHeight * interpolatedTime));
                _view.setLayoutParams(_view.getLayoutParams());
                _view.setRotation(0.0f + (360.0f * interpolatedTime * 2.0f));


            }catch(Exception e){e.printStackTrace();}
        }

        @Override public boolean willChangeBounds() { return true; }

        @Override
        public void onAnimationStart(Animation animation)
        {
            Handler handler = new Handler();
            handler.postDelayed(
                    new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            try
                            {
                                _activity.runOnUiThread(
                                        new Runnable()
                                        {
                                            @Override
                                            public void run()
                                            {
                                                restoreViewSize();
                                            }
                                        }
                                );
                            }catch(Exception e){ e.printStackTrace(); }
                        }
                    },
                    getDuration()
            );
        }

        @Override
        public void onAnimationEnd(Animation animation){

        }

        @Override
        public void onAnimationRepeat(Animation animation){

        }
    }
}

基本上每次调用setValue(强制值)或updateValue(对当前值加减)调用方法setImage设置对应的图像. 根据日志我得到以下结论:

我运行想不出可能是什么问题,有人知道吗?

编辑:添加了扩展 class 和 XML 代码

的代码

这是 AnswerView class 它扩展 SuperMoneyView 以添加 TextView 方法

public class AnswerView extends MoneyView
{
    TextView _answerTextView;
    LinearLayout _answerBoxLinerLayout;
    RelativeLayout _betBoxContainerRelativeLayout;

    private String _answer = "";

    public AnswerView(Context context)
    {
        this(context, null);
    }

    public AnswerView(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public AnswerView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        initConfig(true);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public AnswerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
        initConfig(true);
    }

    @Override
    public void initConfig(boolean setDefaultValues)
    {
        super.initConfig(setDefaultValues);

        _answerTextView = (TextView)findViewById(R.id.answerTextView);
        _moneyValueTextView = (TextView)findViewById(R.id.moneyBetTextView);
        _moneyPacktView = (ImageView)findViewById(R.id.betBoxTextView);
        _answerBoxLinerLayout = (LinearLayout)findViewById(R.id.answerBoxLinerLayout);
        _betBoxContainerRelativeLayout = (RelativeLayout)findViewById(R.id.betBoxContainerRelativeLayout);

        setAnswer(_answer);
        setValue(0l);
    }

    public TextView getTextView()
    {
        return _answerTextView;
    }

    public String getAnswer()
    {
        return _answer;
    }
    public void setAnswer(String answer)
    {
        if(answer == null){ answer = ""; }

        _answer = answer;
        if(_answerTextView != null)
        {
            _answerTextView.setText(_answer);
        }
    }

    public void setNormal()
    {
        _answerBoxLinerLayout.setBackgroundResource(R.drawable.bg_dark_gray_square_blue_border);
        setValue(0l);
        setAlpha(1.0f);
    }
}

class initConfig 在用户选择 start 后由 activity 调用(布局已经绘制并可见)

这是XML代码

<?xml version="1.0" encoding="utf-8"?>
<com.test.game.views.game.AnswerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@android:color/transparent">

    <com.walkme.moneyquiz.views.extended.AutoResizeTextView
        android:id="@+id/answerTextView"
        style="@style/answerTextViewStyle"
        android:text="All at the same time"/>

    <LinearLayout
        android:id="@+id/answerBoxLinerLayout"
        style="@style/answerBetBoxStyle"
        android:orientation="vertical"
        android:background="@drawable/bg_dark_gray_square_blue_border">

        <RelativeLayout
            android:id="@+id/betBoxContainerRelativeLayout"
            style="@style/moneyPackBetRelativeLayoutStyle">

            <ImageView
                android:id="@+id/betBoxTextView"
                style="@style/moneyPackBetImageInRelativeLayoutStyle"
                android:src="@drawable/icn_money_pack_bet_extra_full"/>

        </RelativeLayout>

        <com.walkme.moneyquiz.views.extended.AutoResizeTextView
            android:id="@+id/moneyBetTextView"
            style="@style/betValueTextStyle"
            android:text="5.000$"
            android:singleLine="true"/>

    </LinearLayout>

</com.test.game.views.game.AnswerView>

这是使用 TableRow 内的 include 标签添加到主布局的,具有相等的 weight 分布。

以下是使用的样式:

<style name="answerTextViewStyle">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">0dp</item>
    <item name="android:layout_weight">1</item>
    <item name="android:layout_margin">@dimen/marginSmall</item>
    <item name="android:padding">@dimen/marginSmall</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:textSize">@dimen/textSizeSmall</item>
    <item name="android:gravity">center</item>
    <item name="android:background">@color/mainBlue</item>
</style>
<style name="answerBetBoxStyle">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">0dp</item>
    <item name="android:layout_weight">1</item>
    <item name="android:layout_margin">@dimen/marginSmall</item>
    <item name="android:background">@android:color/transparent</item>
</style>
<style name="moneyPackBetRelativeLayoutStyle">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
</style>
<style name="moneyPackBetImageInRelativeLayoutStyle">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:maxHeight">@dimen/imageHeightMedium</item>
    <item name="android:adjustViewBounds">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:scaleType">centerInside</item>
    <item name="android:layout_gravity">center</item>
    <item name="android:layout_centerInParent">true</item>
</style>
<style name="betValueTextStyle" >
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">0dp</item>
    <item name="android:layout_weight">0.5</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:textSize">@dimen/textSizeMedium</item>
    <item name="android:gravity">center</item>
</style>

根据我从您的代码中了解到的内容,未设置 _moneyPacktView 的默认图像。当 getImageForAmount() 为 0 时,给定 null return 并且带有 null 参数的 setImage() 仅将 _moneyPacktView 设置为可见。也许这就是为什么您的图像不显示的原因。也许您可以在 setImage()

中为 null 参数添加以下代码
if(drawable == null)
{
  Log.e("AnswerView", "setImage -- Drawable Null");
  _moneyPacktView.setImageDrawable(getContext().getResources().getDrawable(R.drawable.anyDefaultImage));
  _moneyPacktView.setAlpha(1.0f);
  _moneyPacktView.setVisibility(View.VISIBLE);
  invalidate();
}

或在您的 getImageForAmount()

 if(amount == 0)
 {
   Log.e("AnswerView", "getImageForAmount -- amount == 0 -- Null");
   return getContext().getResources().getDrawable(R.drawable.anyDefaultImage);
 }

调用无效后检查图像大小。如果尺码不对,强制改正。