OnClick 缩放 ListView (ArrayAdapter) 动画中的图像视图无法正常工作




我在我的应用程序中有一个带有缩略图作为图像视图的列表视图,我希望用户单击缩略图并获取缩放的图像。
就像本教程一样:安卓变焦视图
我的适配器已更新并发布在下面,这是我的ActiviyList:

public class WarmupList extends ListActivity {
    private ListView listView;
    private ArrayList<Warmup> mWarmup = new ArrayList<Warmup>();
    private WarmupAdapter adapter;
    private Runnable viewParts;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_warmup);
        listView = getListView();
        // adapter
        adapter = new WarmupAdapter(this, R.layout.item_warmup, mWarmup);
        listView.setAdapter(adapter);
        // here we are defining our runnable thread.
        viewParts = new Runnable(){
            public void run(){
                handler.sendEmptyMessage(0);
            }
        };
        // here we call the thread we just defined - it is sent to the handler below.
        Thread thread =  new Thread(null, viewParts, "WorkoutThread");
        thread.start();
    }
    private Handler handler = new Handler()
     {
        public void handleMessage(Message msg)
        {
            // TODO entering warmups
            mWarmup.add(new Warmup("Warmup 1", new ArrayList<String>(), "Move left and right like a ho", R.drawable.ic_launcher));
            mWarmup.get(0).getTargetMuscles().add("Shoulders");
            mWarmup.get(0).getTargetMuscles().add("Butt");
            mWarmup.add(new Warmup("Warmup 2", new ArrayList<String>(), "Jump and jump and jump", R.drawable.ic_launcher));
            mWarmup.get(1).getTargetMuscles().add("All muscles");
            mWarmup.get(1).getTargetMuscles().add("Ass too");
            adapter = new WarmupAdapter(WarmupList.this, R.layout.item_warmup, mWarmup);
            setListAdapter(adapter);
        }
    };
}

这能行吗?任何建议将不胜感激!

[EDIT_1] 即使它不合适,我也设法让它工作。我将 zoomImageFromThumb() 添加到适配器。

public class WarmupAdapter extends ArrayAdapter<Warmup> {
    private ArrayList<Warmup> warmups;
    private LayoutInflater inflater;
    private TextView warmupNameView;
    private TextView targetMuscles;
    private TextView warmupInfo;
    private View warmupImage;
    public WarmupAdapter(Context context, int textViewResourceId,
            ArrayList<Warmup> objects) {
        super(context, textViewResourceId, objects);
        warmups = objects;
        inflater = (LayoutInflater) getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        // Retrieve and cache the system's default "short" animation time.
        mShortAnimationDuration = getContext().getResources().getInteger(
                android.R.integer.config_shortAnimTime);
    }
    public View getView(int position, final View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null)
            view = inflater.inflate(R.layout.item_warmup, null);
        warmupNameView = (TextView) view.findViewById(R.id.tv_warmup_name);
        targetMuscles = (TextView) view.findViewById(R.id.tv_warmup_muscle);
        warmupInfo = (TextView) view.findViewById(R.id.tv_warmup_info);
        warmupImage = (ImageView) view.findViewById(R.id.thumb_button_1);
        final Warmup warmup = warmups.get(position);
        if (warmup != null) {
            warmupNameView.setText(warmup.getName());
            targetMuscles.setText("Target Muscles: "
                    + warmup.getTargetMuscles().get(0));
            ((ImageView) warmupImage).setImageResource(warmup.getThumbResId());
            for (int i = 1; i < warmup.getTargetMuscles().size(); i++) {
                targetMuscles.setText(targetMuscles.getText() + ", "
                        + warmup.getTargetMuscles().get(i));
            }
            warmupInfo.setText(warmup.getInfo());
            warmupImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    zoomImageFromThumb(warmupImage, warmup.getImageResId());
                    Toast.makeText(getContext(), "on click works", Toast.LENGTH_SHORT).show();
                }
            });
        }
        return view;
    }
    private Animator mCurrentAnimator;
    private int mShortAnimationDuration;
    private void zoomImageFromThumb(final View thumbView,
            int imageResId) {
        // get container and image view from warmupList activity

        // If there's an animation in progress, cancel it immediately and
        // proceed with this one.
        if (mCurrentAnimator != null) {
            mCurrentAnimator.cancel();
        }
        // Load the high-resolution "zoomed-in" image.
        final ImageView expandedImageView = WarmupList.imageView;
        expandedImageView.setImageResource(imageResId);
        // Calculate the starting and ending bounds for the zoomed-in image.
        // This step
        // involves lots of math. Yay, math.
        final Rect startBounds = new Rect();
        final Rect finalBounds = new Rect();
        final Point globalOffset = new Point();
        // The start bounds are the global visible rectangle of the thumbnail,
        // and the
        // final bounds are the global visible rectangle of the container view.
        // Also
        // set the container view's offset as the origin for the bounds, since
        // that's
        // the origin for the positioning animation properties (X, Y).
        thumbView.getGlobalVisibleRect(startBounds);
        WarmupList.containerView.getGlobalVisibleRect(finalBounds,
                globalOffset);
        startBounds.offset(-globalOffset.x, -globalOffset.y);
        finalBounds.offset(-globalOffset.x, -globalOffset.y);
        // Adjust the start bounds to be the same aspect ratio as the final
        // bounds using the
        // "center crop" technique. This prevents undesirable stretching during
        // the animation.
        // Also calculate the start scaling factor (the end scaling factor is
        // always 1.0).
        float startScale;
        if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds
                .width() / startBounds.height()) {
            // Extend start bounds horizontally
            startScale = (float) startBounds.height() / finalBounds.height();
            float startWidth = startScale * finalBounds.width();
            float deltaWidth = (startWidth - startBounds.width()) / 2;
            startBounds.left -= deltaWidth;
            startBounds.right += deltaWidth;
        } else {
            // Extend start bounds vertically
            startScale = (float) startBounds.width() / finalBounds.width();
            float startHeight = startScale * finalBounds.height();
            float deltaHeight = (startHeight - startBounds.height()) / 2;
            startBounds.top -= deltaHeight;
            startBounds.bottom += deltaHeight;
        }
        // Hide the thumbnail and show the zoomed-in view. When the animation
        // begins,
        // it will position the zoomed-in view in the place of the thumbnail.
        thumbView.setAlpha(0f);
        expandedImageView.setVisibility(View.VISIBLE);
        // Set the pivot point for SCALE_X and SCALE_Y transformations to the
        // top-left corner of
        // the zoomed-in view (the default is the center of the view).
        expandedImageView.setPivotX(0f);
        expandedImageView.setPivotY(0f);
        // Construct and run the parallel animation of the four translation and
        // scale properties
        // (X, Y, SCALE_X, and SCALE_Y).
        AnimatorSet set = new AnimatorSet();
        set.play(
                ObjectAnimator.ofFloat(expandedImageView, View.X,
                        startBounds.left, finalBounds.left))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                        startBounds.top, finalBounds.top))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
                        startScale, 1f))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y,
                        startScale, 1f));
        set.setDuration(mShortAnimationDuration);
        set.setInterpolator(new DecelerateInterpolator());
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mCurrentAnimator = null;
            }
            @Override
            public void onAnimationCancel(Animator animation) {
                mCurrentAnimator = null;
            }
        });
        set.start();
        mCurrentAnimator = set;
        // Upon clicking the zoomed-in image, it should zoom back down to the
        // original bounds
        // and show the thumbnail instead of the expanded image.
        final float startScaleFinal = startScale;
        expandedImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mCurrentAnimator != null) {
                    mCurrentAnimator.cancel();
                }
                // Animate the four positioning/sizing properties in parallel,
                // back to their
                // original values.
                AnimatorSet set = new AnimatorSet();
                set.play(
                        ObjectAnimator.ofFloat(expandedImageView, View.X,
                                startBounds.left))
                        .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                                startBounds.top))
                        .with(ObjectAnimator.ofFloat(expandedImageView,
                                View.SCALE_X, startScaleFinal))
                        .with(ObjectAnimator.ofFloat(expandedImageView,
                                View.SCALE_Y, startScaleFinal));
                set.setDuration(mShortAnimationDuration);
                set.setInterpolator(new DecelerateInterpolator());
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }
                });
                set.start();
                mCurrentAnimator = set;
            }
        });
    }

}

我使用以下方法从列表活动中获取容器视图和图像视图:

public static View containerView;
public static ImageView imageView;

并在 onCreate 方法的 列表活动:

containerView = findViewById(R.id.container);
imageView = (ImageView) findViewById(R.id.expanded_image);

现在,当我单击每个拇指视图时,我会缩放所需的图像,但您可能已经注意到 zoomImageFromThumb() 方法隐藏了单击的拇指视图并为其投射动画。问题是,无论我单击哪个拇指视图,列表视图中的最后一个拇指视图始终是动画的并设置为不可见。

[Edit_2] 没关系,伙计们,我解决了问题,工作得很好。如果有人偶然发现同样的问题,请告诉我,我会发布答案。

这是我

最终的 WarmupAdapter.java 的样子:

public class WarmupAdapter extends ArrayAdapter<Warmup> {
    private ArrayList<Warmup> warmups;  private LayoutInflater inflater;
    private TextView warmupNameView;    private TextView targetMuscles;
    public WarmupAdapter(Context context, int textViewResourceId,           ArrayList<Warmup> objects) {        super(context, textViewResourceId, objects);
        warmups = objects;      inflater = (LayoutInflater) getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
                // Retrieve and cache the system's default "short" animation time.      mShortAnimationDuration = getContext().getResources().getInteger(
                android.R.integer.config_shortAnimTime);
    }
    public View getView(int position, final View convertView, ViewGroup parent) {       View view = convertView;        View warmupImage;
                if (view == null)           view = inflater.inflate(R.layout.item_warmup, null);
        warmupNameView = (TextView) view.findViewById(R.id.tv_warmup_name);         targetMuscles = (TextView) view.findViewById(R.id.tv_warmup_muscle);
                warmupImage = (ImageView) view.findViewById(R.id.thumb_button_1);
        final Warmup warmup = warmups.get(position);
        if (warmup != null) {           warmupNameView.setText(warmup.getName());           targetMuscles.setText("Targets: "
                    + warmup.getTargetMuscles().get(0));
            ((ImageView) warmupImage).setImageResource(warmup.getThumbResId());
            for (int i = 1; i < warmup.getTargetMuscles().size(); i++) {
                targetMuscles.setText(targetMuscles.getText() + ", "
                        + warmup.getTargetMuscles().get(i));            }
            warmupImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ImageView wmpImage = (ImageView) v.findViewById(R.id.thumb_button_1);
                    zoomImageFromThumb(wmpImage, warmup.getImageResId());
                }           });
                    }
                return view;    }
    private Animator mCurrentAnimator;
    private int mShortAnimationDuration;
    private void zoomImageFromThumb(final View thumbView,           int imageResId) {
        // If there's an animation in progress, cancel it immediately and       // proceed with this one.       if (mCurrentAnimator != null) {             mCurrentAnimator.cancel();      }       // Load the high-resolution "zoomed-in" image.      final ImageView expandedImageView = WarmupList.imageView;       expandedImageView.setImageResource(imageResId);
        // Calculate the starting and ending bounds for the zoomed-in image.        // This step        // involves lots of math. Yay, math.        final Rect startBounds = new Rect();        final Rect finalBounds = new Rect();        final Point globalOffset = new Point();
        // The start bounds are the global visible rectangle of the thumbnail,      // and the      // final bounds are the global visible rectangle of the container view.         // Also         // set the container view's offset as the origin for the bounds, since      // that's       // the origin for the positioning animation properties (X, Y).      thumbView.getGlobalVisibleRect(startBounds);        WarmupList.containerView.getGlobalVisibleRect(finalBounds,
                globalOffset);      startBounds.offset(-globalOffset.x, -globalOffset.y);       finalBounds.offset(-globalOffset.x, -globalOffset.y);
        // Adjust the start bounds to be the same aspect ratio as the final         // bounds using the         // "center crop" technique. This prevents undesirable stretching during         // the animation.       // Also calculate the start scaling factor (the end scaling factor is       // always 1.0).         float startScale;       if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds
                .width() / startBounds.height()) {          // Extend start bounds horizontally             startScale = (float) startBounds.height() / finalBounds.height();           float startWidth = startScale * finalBounds.width();            float deltaWidth = (startWidth - startBounds.width()) / 2;          startBounds.left -= deltaWidth;             startBounds.right += deltaWidth;        } else {            // Extend start bounds vertically           startScale = (float) startBounds.width() / finalBounds.width();             float startHeight = startScale * finalBounds.height();          float deltaHeight = (startHeight - startBounds.height()) / 2;           startBounds.top -= deltaHeight;             startBounds.bottom += deltaHeight;      }
        // Hide the thumbnail and show the zoomed-in view. When the animation       // begins,      // it will position the zoomed-in view in the place of the thumbnail.       thumbView.setAlpha(0f);         expandedImageView.setVisibility(View.VISIBLE);
        // Set the pivot point for SCALE_X and SCALE_Y transformations to the       // top-left corner of       // the zoomed-in view (the default is the center of the view).      expandedImageView.setPivotX(0f);        expandedImageView.setPivotY(0f);
        // Construct and run the parallel animation of the four translation and         // scale properties         // (X, Y, SCALE_X, and SCALE_Y).        AnimatorSet set = new AnimatorSet();        set.play(
                ObjectAnimator.ofFloat(expandedImageView, View.X,
                        startBounds.left, finalBounds.left))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                        startBounds.top, finalBounds.top))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
                        startScale, 1f))
                .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y,
                        startScale, 1f));       set.setDuration(mShortAnimationDuration);       set.setInterpolator(new DecelerateInterpolator());      set.addListener(new AnimatorListenerAdapter() {             @Override           public void onAnimationEnd(Animator animation) {
                mCurrentAnimator = null;            }
            @Override           public void onAnimationCancel(Animator animation) {
                mCurrentAnimator = null;            }       });         set.start();        mCurrentAnimator = set;
        // Upon clicking the zoomed-in image, it should zoom back down to the       // original bounds      // and show the thumbnail instead of the expanded image.        final float startScaleFinal = startScale;       expandedImageView.setOnClickListener(new View.OnClickListener() {           @Override           public void onClick(View view) {
                if (mCurrentAnimator != null) {
                    mCurrentAnimator.cancel();
                }
                // Animate the four positioning/sizing properties in parallel,
                // back to their
                // original values.
                AnimatorSet set = new AnimatorSet();
                set.play(
                        ObjectAnimator.ofFloat(expandedImageView, View.X,
                                startBounds.left))
                        .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                                startBounds.top))
                        .with(ObjectAnimator.ofFloat(expandedImageView,
                                View.SCALE_X, startScaleFinal))
                        .with(ObjectAnimator.ofFloat(expandedImageView,
                                View.SCALE_Y, startScaleFinal));
                set.setDuration(mShortAnimationDuration);
                set.setInterpolator(new DecelerateInterpolator());
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
                        thumbView.setAlpha(1f);
                        expandedImageView.setVisibility(View.GONE);
                        mCurrentAnimator = null;
                    }
                });
                set.start();
                mCurrentAnimator = set;             }       });     }
     }

最新更新