问题
Background
I have a ViewPager (of images pages), which needs to show its content inside an image that should keep its aspect ratio.
The problem
Problem is, when I just set a 9-patch for any kind of ViewGroup (including the ViewPager), the image just stretches (not keeping the aspect-ratio), and for some reason, it doesn't even respect the content bounding box I've set to it (in the 9-patch).
It occurs even if I put the ViewPager in a FrameLayout that has the 9-patch background instead.
What I've tried
I've tried to overcome this by not using 9-patch at all. I used a RelativeLayout with ImageView (of the image) , and the ViewPager set to align exactly to the ImageView.
Of course, this wasn't enough, since the ImageView doesn't take the same space as what it shows, so I had to calculate the padding needed to fix it, based on the image size and the imageView size, and then set it on a FrameLayout that includes the ViewPager. This almost works, but it has issues too (not precise calculations, which could cause one pixel row to show/hide of the viewPager).
The question
Is it possible to set a background for ViewPager (or any other ViewGroup), that will keep its aspect ratio, yet also allow padding using 9-patch?
回答1:
ok, so what I did is this:
- set the 9-patch as a background to the parent of the ViewPager, or to the ViewPager itself.
- right when you get the size of the view, calculate what should be the width or height of it, depending on the bitmap size and the restrictions you have, and set it to the view.
In my case, the restrictions were to fill it to the height of the parent, so what I needed is to calculate the needed width...
Weird thing, is that I still see artefacts. The bottom of the viewpager has about 1-2 pixels rows of the background instead of being of itself (the "hole" of the 9-patch is at the bottom of the image).
EDIT: fixed it too. Seems to be an issue with various screen pixels-densities. Here's a snippet:
public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) {
final OnPreDrawListener preDrawListener = new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
runnable.run();
return true;
}
};
view.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
}
public static BitmapFactory.Options getBitmapOptions(final Resources res, final int resId) {
final BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, bitmapOptions);
return bitmapOptions;
}
final Options bitmapOptions = getBitmapOptions(getResources(), R.drawable.nine_patch_image);
final View viewPagerContainer = ...;
runJustBeforeBeingDrawn(viewPagerContainer, new Runnable() {
@Override
public void run() {
int neededWidth = (int)Math.ceil((float) bitmapOptions.outWidth * viewPagerContainer.getHeight() / bitmapOptions.outHeight);
final LayoutParams layoutParams = viewPagerContainer.getLayoutParams();
layoutParams.width=neededWidth;
viewPagerContainer.setLayoutParams(layoutParams);
}
});
EDIT: Alternative to runJustBeforeBeingDrawn: https://stackoverflow.com/a/28136027/878126
来源:https://stackoverflow.com/questions/31229007/how-to-set-9-patch-background-for-viewpager-that-will-put-the-pages-inside-and