getWidth() возвращает 0 в onCreateView()

Я начинаю собирать изображение из галереи, затем масштабирую изображение и динамически добавляю ImageView к макету.

Я хочу, чтобы это изображение было перезагружено при изменении ориентации. Я устанавливаю setRetainInstance (true) в onCreate. Тем не менее, после изменения ориентации, когда я пытаюсь получить соответствующую ширину для растрового изображения, которое нужно масштабировать, вызывая getWidth() для FrameLayout, который должен быть его контейнером, я получаю 0.

public class NewWallpaper extends Fragment {
    private static final int PICK_BACKGROUND = 1;

    private BitmapFactory.Options bitmapFactoryOptions;

    // Data
    private Uri backgroundURI = null;
    private WeakReference<Bitmap> backgroundBitmap = null;

    // Views
    FrameLayout backgroundContainer;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_new_wallpaper, container, false);

        // BitmapFactory options
        bitmapFactoryOptions = new BitmapFactory.Options();
        bitmapFactoryOptions.inPurgeable = true;

        Button pickBackground = (Button) view.findViewById(R.id.buttonPickBackground);
        pickBackground.setOnClickListener(pickBackgroundListener);

        backgroundContainer = (FrameLayout) view.findViewById(R.id.frameLayoutbackgroundContainer);

        if (backgroundURI != null)
            setBackgroundPreview();

        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }


    private Button.OnClickListener pickBackgroundListener = new Button.OnClickListener() {

        @Override
        public void onClick(View view) {
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, PICK_BACKGROUND);
        }
    };

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == PICK_BACKGROUND && resultCode == getActivity().RESULT_OK && data != null && data.getData() != null) {
            backgroundURI = data.getData();
            setBackgroundPreview();
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void setBackgroundPreview() {
        try {
            backgroundContainer.removeAllViews();

            Bitmap background = BitmapHelper.loadScaledBitmap(getActivity(), backgroundURI, backgroundContainer.getWidth());

            backgroundBitmap = new WeakReference<Bitmap>(background);

            // returns 0
            int containerWidth = backgroundContainer.getWidth();

            ImageView backgroundView = new ImageView(getActivity());
            backgroundView.setLayoutParams(new LinearLayout.LayoutParams(
                    backgroundContainer.getWidth(),
                    BitmapHelper.calculateHeight(
                            background.getWidth(),
                            background.getHeight(),
                            backgroundContainer.getWidth())
            ));
            backgroundView.setAdjustViewBounds(true);
            backgroundView.setScaleType(ImageView.ScaleType.FIT_XY);
            backgroundView.setImageBitmap(background);

            backgroundContainer.addView(backgroundView);

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

Кажется, я не могу найти способ заселить представления после изменения ориентации. Может кто-нибудь сказать мне, что я делаю не так?

3 ответа

Не звони setBackgroundPreview() от onCreateView, Вы не можете измерить вид, если он еще не закончен.

Вызов setBackgroundPreview() в onActivityCreated вместо.

Если вы хотите ширину в пикселях, вы должны вместо этого вызвать view.getMeasuredWidth (). getWidth () и getHeight () дадут вам

LayoutParams.WRAP_CONTENT | LayoutParams.MATCH_PARENT  //constants (1 or 0).

Тем не менее, чтобы убедиться, что вы получаете правильное значение, вызовите этот метод после обратного вызова @onDraw () вашего представления (переопределите его) или получите viewTreeObserver и дождитесь обратного вызова onGlobalLayout() для вызова методов.

<<<<< РЕДАКТИРОВАТЬ: >>>>>

Найден один пример с ViewTreeObserver:

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      viewWidth = mediaGallery.getMeasuredWidth();
      viewHeight = mediaGallery.getMeasuredHeight();
    }
  });
}

Удаление прослушивателя после первого обратного вызова гарантирует освобождение большого количества процесса, поскольку нам нужны только один раз измеренные параметры.

Ширина и высота не определяются до тех пор, пока вид фактически не отобразится на экране. Собранные из getWidth и getHeight возвращают ноль. Также вы проверяете этот пост Как вам получить размеры представления? Getheight () и Getwidth() всегда возвращают ноль

Другие вопросы по тегам