如何在每次绘制到 UI 之前获取 ImageView 的高度和宽度(在片段中)
How to get ImageView Height and Width every time, before it is drawn to the UI (in a Fragment)
我想将外部存储中的照片设置为(圆形)ImageView。因此我有一个函数,要求 ImageView 的高度和宽度,裁剪图片,然后将其设置为位图。
我的问题是,这个函数在 UI 加载之前被调用。我遇到了解决方案,我第一次调用这个函数,在 onViewCreated 中,我在其中添加了一个监听器到 addOnWindowFocusChangeListener。这是第一次工作。
该片段位于 ViewPager 内,如果我转到左侧的片段,然后越过中间向右,它又消失了。
我是 Whosebug 的新手。我感谢每一个提示,我可以做得更好。
//This works for the First Time
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View m = getView();
ViewTreeObserver n = m.getViewTreeObserver();
n.addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
@Override
public void onWindowFocusChanged(final boolean hasFocus) {
// do your stuff here
ImageUtil.setPic(binding.photoRoundProfile, mCurrentPhotoPath);
}
});
}
//The function where I set the Picture into the ImageView
static public void setPic(ImageView mImageView, String pPath) {
try {
if (pPath == null) return;
File f = new File(pPath);
if (!f.exists() || f.isDirectory()) return;
// Get the dimensions of the View
int targetW = mImageView.getWidth();
if (targetW == 0) targetW = mImageView.getMeasuredWidth();
int targetH = mImageView.getHeight();
if (targetH == 0) targetH = mImageView.getMeasuredHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = photoW / targetW; //Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(pPath, bmOptions);
Bitmap orientedBitmap = ExifUtil.rotateBitmap(pPath, bitmap);
mImageView.setImageBitmap(orientedBitmap);
//mImageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
mImageView.setAdjustViewBounds(true);
mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} catch (Exception e) {
e.printStackTrace();
}
}
有视频,方便理解:https://www.loom.com/share/05c4174562d74c9bba8ff02c9072c866
我找到了解决问题的办法。我在 OnPreDrawListener
中找到了方法 onPreDraw
。每次更新 ImageView
时都会运行此侦听器。因此我添加了一个 if-Statement 来节省性能而不是每次都重绘。
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView iv= binding.photoRoundProfile;
ViewTreeObserver vto = iv.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
private int mFinalWidth = 0;
private int mFinalHeight = 0;
public boolean onPreDraw() {
if(mFinalHeight != 0 || mFinalWidth != 0)
return true;
mFinalHeight = iv.getHeight();
mFinalWidth = iv.getWidth();
Log.d("hilength","Height: " + mFinalHeight + " Width: " + mFinalWidth);
ImageUtil.setPic(binding.photoRoundProfile, mCurrentPhotoPath);
return true;
}
});
}
我想将外部存储中的照片设置为(圆形)ImageView。因此我有一个函数,要求 ImageView 的高度和宽度,裁剪图片,然后将其设置为位图。
我的问题是,这个函数在 UI 加载之前被调用。我遇到了解决方案,我第一次调用这个函数,在 onViewCreated 中,我在其中添加了一个监听器到 addOnWindowFocusChangeListener。这是第一次工作。
该片段位于 ViewPager 内,如果我转到左侧的片段,然后越过中间向右,它又消失了。
我是 Whosebug 的新手。我感谢每一个提示,我可以做得更好。
//This works for the First Time
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View m = getView();
ViewTreeObserver n = m.getViewTreeObserver();
n.addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
@Override
public void onWindowFocusChanged(final boolean hasFocus) {
// do your stuff here
ImageUtil.setPic(binding.photoRoundProfile, mCurrentPhotoPath);
}
});
}
//The function where I set the Picture into the ImageView
static public void setPic(ImageView mImageView, String pPath) {
try {
if (pPath == null) return;
File f = new File(pPath);
if (!f.exists() || f.isDirectory()) return;
// Get the dimensions of the View
int targetW = mImageView.getWidth();
if (targetW == 0) targetW = mImageView.getMeasuredWidth();
int targetH = mImageView.getHeight();
if (targetH == 0) targetH = mImageView.getMeasuredHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = photoW / targetW; //Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(pPath, bmOptions);
Bitmap orientedBitmap = ExifUtil.rotateBitmap(pPath, bitmap);
mImageView.setImageBitmap(orientedBitmap);
//mImageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
mImageView.setAdjustViewBounds(true);
mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} catch (Exception e) {
e.printStackTrace();
}
}
有视频,方便理解:https://www.loom.com/share/05c4174562d74c9bba8ff02c9072c866
我找到了解决问题的办法。我在 OnPreDrawListener
中找到了方法 onPreDraw
。每次更新 ImageView
时都会运行此侦听器。因此我添加了一个 if-Statement 来节省性能而不是每次都重绘。
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView iv= binding.photoRoundProfile;
ViewTreeObserver vto = iv.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
private int mFinalWidth = 0;
private int mFinalHeight = 0;
public boolean onPreDraw() {
if(mFinalHeight != 0 || mFinalWidth != 0)
return true;
mFinalHeight = iv.getHeight();
mFinalWidth = iv.getWidth();
Log.d("hilength","Height: " + mFinalHeight + " Width: " + mFinalWidth);
ImageUtil.setPic(binding.photoRoundProfile, mCurrentPhotoPath);
return true;
}
});
}