我的应用程序中有一个带缩略图的ListView作为ImageViews,我希望用户单击缩略图并获得缩放的图像。
就像本教程一样:
Android Zoom View
我的适配器已更新并发布在下面,这是我的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;
}
});
}
}
我使用以下方法从列表活动中获取containerView和imageView:
public static View containerView;
public static ImageView imageView;
并在listActivity的onCreate方法中:
containerView = findViewById(R.id.container);
imageView = (ImageView) findViewById(R.id.expanded_image);
现在,当我单击每个thumbView时,都会放大所需的图像,但是您可能已经注意到zoomImageFromThumb()方法隐藏了被单击的thumbView并为其投射了动画。问题是,无论我单击哪个thumbView,总是将ListView中的最后一个thumbView设置为动画并设置为不可见。
[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; } }); }
}