Arhn - архитектура программирования

Android - рисование ImageView точно поверх существующего представления в более глубоком слое

Это сложная ситуация для описания, поэтому, пожалуйста, потерпите меня. Меня попросили сделать экран «оценки тренера» примерно таким:

введите здесь описание изображения

Однако в моем случае мне нужно «вытянуть» некоторые из основных изображений на передний план и отобразить их другим цветом, чтобы они выделялись. Я не могу определить, каким будет «кадр» этих изображений до запуска. Мой подход состоит в том, чтобы добавить черный полупрозрачный вид (я называю его «занавес»), покрывающий весь экран, а затем добавить нужные мне изображения в качестве подвидов занавеса другого цвета. EDIT Эта часть проста, и я не прошу помощи в этом (поэтому предположение, что это дубликат предложенного вопроса, неверно).

Я не думаю, что смогу использовать bringToFront() или setTranslationZ(), потому что эти методы не выведут ImageView полностью на переднюю часть моего занавеса. Итак, что я пытаюсь сделать, это получить точную «рамку» представления изображения (его x, y, ширина и высота) относительно всего экрана, а затем попытаться добавить новый просмотр изображения с использованием того же чертежа с тем же кадром.

Также важно знать, что базовый «представление» на самом деле состоит из нескольких представлений (включая выдвижной ящик), поэтому мне нужно получить координаты относительно экрана. Я надеюсь это имеет смысл.

Я могу нарисовать новый ImageView как часть занавеса с правильным цветом, но положение и размер изображения далеко. Как я могу нарисовать этот новый ImageView точно поверх предыдущего?

Я также открыт для других стратегий (поскольку этот, кажется, не работает). Спасибо за любую помощь.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ...

    ViewTreeObserver vto = mRootview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            mRootview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            mDrawerLayout.openDrawer(Gravity.LEFT);

            RelativeLayout curtain = addOpaqueCurtainToRootView();
            int frame[] = getFrameOfExistingImageView();
            addNewImageViewOnTopOfEverything(curtain, frame);
        }
    });
}

private RelativeLayout addOpaqueCurtainToRootView() {
    RelativeLayout curtain = new RelativeLayout(context);
    RelativeLayout.LayoutParams curtainParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
    curtain.setLayoutParams(curtainParams);
    curtain.setBackgroundColor(Color.argb(179, 0, 0, 0)); //70% opaque
    mRootview.addView(curtain);
    return curtain;
}

private int[] getFrameOfExistingImageView() {
    // proving that I have a reference to the original image
    mCurrentImage.setColorFilter(Color.rgb(255, 0, 0));

    int array[] = new int[2];
    mCurrentImage.getLocationOnScreen(array);
    Log.d(TAG, "width: " + Integer.toString(array[0]));
    Log.d(TAG, "height: " + Integer.toString(array[1]));
    Log.d(TAG, "x: " + Float.toString(mCurrentImage.getX()));
    Log.d(TAG, "y: " + Float.toString(mCurrentImage.getY()));

    int frame[] = new int[4]; // x,y,width,height
    frame[0] = (int)mCurrentImage.getX();
    frame[1] = (int)mCurrentImage.getY();
    frame[2] = array[0];
    frame[3] = array[1];
    return frame;
}

private void addNewImageViewOnTopOfEverything(RelativeLayout curtain, int[] frame) {
    ImageView iv = new ImageView(context);
    iv.setImageResource(R.drawable.imgView);
    iv.setColorFilter(Color.rgb(255, 255, 255));
    iv.setX(frame[0]);
    iv.setY(frame[1]);
    iv.setLayoutParams(new RelativeLayout.LayoutParams(frame[2], frame[3]));

    curtain.addView(iv);
}
16.07.2016

  • Возможный дубликат Как создать прозрачную активность в Android? 16.07.2016
  • попробуйте это 16.07.2016
  • @ user5599807 - не дубликат. В этом посте задается очень простой вопрос: как нарисовать вид с полупрозрачным фоном. Я уже делаю это (легко). Мой вопрос о том, как разместить дочерние представления в этом новом представлении в точном положении и с точным размером. 16.07.2016
  • @pskink - спасибо за это. Когда я читаю этот код, кажется, что решение состоит в следующем: а) получить ссылку на представление изображения, б) удалить его из исходного родительского представления, а затем в) добавить его в новое полупрозрачное представление. Но это не решает вопроса о том, как расположить и изменить размер изображения в новом родительском элементе, верно? Я, наверное, не понимаю, как правильно реализовать это предложение. Есть ли что-то большее, чем то, что я вижу? Большое спасибо за все, что вы можете предложить. Я признателен за это! 16.07.2016
  • ImageView не требуется: нарисуйте все, что хотите, в методе dispatchDraw, вы можете вызвать, например, canvas.drawBitmap, MyDecorView занимает весь экран, включая панель действий, поэтому вам не нужно его позиционировать каким-либо образом, просто вызовите addMeToTheViewTree после вызова setContentView 16.07.2016
  • Ok. Думаю, мне есть что почитать о классе Canvas. Спасибо. 16.07.2016

Ответы:


1

Я понял это. У меня было две основные проблемы.

Во-первых, я неправильно понял рамку ImageView. Мне нужно было получить левые и верхние координаты, а также высоту и ширину изображения после его рисования. Вот как я это делаю (на самом деле я конвертирую влево, вверх, вправо, вниз, но остальное легко):

private int[] getFrameOfImageView(ImageView imageView) {

    int array[] = new int[2];
    imageView.getLocationOnScreen(array);

    int frame[] = new int[4];

    frame[0] = array[0]; // left
    frame[1] = array[1]; // top
    frame[2] = array[0] + imageView.getWidth(); // right
    frame[3] = array[1] + imageView.getHeight(); // bottom

    return frame;
}

Затем я создал новый класс для рисования. Это самое большое отличие от моего ОП. Первоначально я думал, что могу просто добавить это как новый ImageView и установить его LayoutParams, чтобы разместить его там, где я хотел. Вместо этого я использовал Paint и Canvas для рисования, изменения размеров и размещения:

public class CanvasPainter extends View {

    Context mContext;
    Drawable mDrawable;

    int mFrame[];
    int left;
    int top;
    int right;
    int bottom;
    int width;
    int height;

    private final int LEFT = 0;
    private final int TOP = 1;
    private final int RIGHT = 2;
    private final int BOTTOM = 3;

    public CanvasPainter(Context context, int frame[], Drawable drawable) {
        super(context);

        mContext = context;
        mFrame = frame;
        mDrawable = drawable;

        left = frame[LEFT];
        top = frame[TOP];
        right = frame[RIGHT];
        bottom = frame[BOTTOM];
        width = right - left;
        height = bottom - top;

    }

    public void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);


        Bitmap b = ((BitmapDrawable) mDrawable).getBitmap();
        Bitmap bitmapResized = Bitmap.createScaledBitmap(b, width, height, false);

        canvas.drawBitmap(bitmapResized, left, top, paint);
    }
}

Итак, соберите это вместе, все это организовано из onCreate() вот так;

@Override 
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ... 

    mDrawerLayout.openDrawer(Gravity.LEFT);

    ViewTreeObserver vto = mRootview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override 
        public void onGlobalLayout() { 

            mRootview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            RelativeLayout curtain = addOpaqueCurtainToRootView();
            int frame[] = getFrameOfExistingImageView();
            Drawable d = ContextCompat.getDrawable(context, R.drawable.imgView);
            CanvasPainter canvasPainter = new CanvasPainter(context, mCurrentImg, frame, d);
            curtain.addView(canvasPainter);
        } 
    }); 
} 

Может быть, это немного неясная проблема, но я надеюсь, что это поможет кому-то.

17.07.2016
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..