1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/vigiles-UScaleView

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

colorLineNode, sizeLongOfLineNode, spaceBetweenLine, touchEnable — это параметры, которые были настроены в файле attrs.xml.

Необходимо обратить внимание на то, что свойства не объявляются в конструкторе View. Они инициализируются только при использовании. Поэтому объявленные свойства не всегда являются активными. Также было упомянуто, что если свойство не объявлено, то мы присвоим ему значение по умолчанию.

Рассмотрим пространство имён cuiweiyou:

<github>
pics/02.png ""

В файле макета (layout) объявляется xmlns с именем cuiweiyou как ссылка на пакет проекта.

2. Высота столбцов

Сначала необходимо определить жизненный цикл View и посмотреть на упрощённую схему регистрации жизненного цикла в XML:

<github>
pics/03.png ""

Независимо от того, сколько раз выполняется onMeasure, в конечном итоге будет выполнен onLayout для определения позиции дочерних элементов. А затем будет выполнен onDraw для отрисовки элемента управления.

Во время выполнения onMeasure определяется ширина и высота элемента управления, а во время onLayout — позиция дочерних элементов. Однако для получения окончательной ширины и высоты элемента управления обычно используется метод get во время onLayout, и это значение является точным.

(1) Высота элемента управления

Вот пример типичного кода:

/**
 * Измерение ширины и высоты текущего элемента управления
 * TODO wrap_content ещё не обработан (включая ширину и высоту накопленных линий и текста)
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int widthMode = MeasureSpec.getMode(widthMeasureSpec); // Получить режим измерения ширины
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); // Получить размер измерения ширины
    int heightMode = MeasureSpec.getMode(heightMeasureSpec); // Получить режим измерения высоты
    int heightSize = MeasureSpec.getSize(heightMeasureSpec); // Получить размер измерения высоты
    int width;
    int height;

    if (widthMode == MeasureSpec.EXACTLY) { // Если режим измерения ширины точно задан
        width = widthSize;
    } else { // Иначе
        width = (int) (getPaddingLeft() + getPaddingRight()); // 1.
    }
    if (heightMode == MeasureSpec.EXACTLY) { // Если режим измерения высоты точно задан
        height = heightSize;
    } else { // Иначе
        height = (int) (getPaddingTop() + getPaddingBottom()); // 2.
    }

    setMeasuredDimension(width, height);
}

Этот код применим только к match_parent и конкретной dp. Если это wrap_content, то также необходимо добавить ширину и высоту дочерних элементов в строки 1 и 2.

(2) Позиционирование элементов

Пример кода для получения окончательной высоты и ширины элемента управления:

Кроме получения ширины и высоты, также необходимо выполнить вычисления на основе конфигурации линии сетки, максимального и минимального значений и т. д., чтобы оптимизировать эффект отрисовки. Например, этот элемент управления занимает определённую ширину и высоту на экране. Если он ограничен по высоте, то можно вычислить интервал между линиями сетки на основе максимального и минимального значения. Если полученное значение отличается от настроенного значения, его необходимо обработать.

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

3. Позиция градиента цвета

(1) Создание градиента

Для создания градиента в Android используется объект LinearGradient. Обычно используется один из следующих конструкторов:

LinearGradient shader = new LinearGradient(
    starX, // Начальная точка x
    0, // Начальная точка y
    starX, // Конечная точка x
    height - paddingBottom, // Конечная точка y
    new int[]{ // Массив цветов, начиная с верхней части экрана и заканчивая нижней частью
        Color.RED,
        Color.YELLOW,
        Color.GREEN},
    null, // Переходные позиции new float[]{0 , 0.5f, 1.0f}, длина и массив цветов совпадают
    Shader.TileMode.REPEAT); // CLAMP: растяжение пикселей на границе. REPEAT: равномерное повторение растрового изображения. MIRROR: зеркальное рендеринг.

Обратите внимание на понимание первых четырёх параметров, определяющих направление градиента:

<github>
pics/04.png ""

Вертикальные пиксели имеют одинаковый цвет.

Шестой параметр, если он равен null, то цвета распределяются равномерно в соответствии с длиной массива цветов. В противном случае они распределяются в соответствии со значением, указанным в параметре. Конечно, длина двух массивов должна быть одинаковой.

Седьмой параметр, Shader.TileMode, имеет три параметра: CLAMP, REPEAT и MIRROR. CLAMP используется для копирования цвета границы, когда рендерер выходит за пределы исходного диапазона границ. REPEAT используется для равномерного повторения растрового изображения по горизонтали и вертикали. MIRROR используется для зеркального рендеринга по горизонтали и вертикали.

(2) Рисование

Используйте этот градиент в качестве цвета кисти:

Paint paint = new Paint();
paint.setShader(shader); // Установить градиент цвета заливки

LinearGradient определяет направление градиента (расстояние, на котором происходит градиент), и когда кисть находится в определённом положении, пиксель, который она рисует, соответствует цвету. Когда расстояние превышает указанное расстояние, оно рисуется в соответствии с указанным режимом TileMode или зеркально отражается, или растягивается и т.д.

Что касается того, насколько большой рисунок может нарисовать кисть, это зависит от Canvas:

// Определить прямоугольник (левый верхний правый нижний)
RectF cylinder = new RectF(starX, paddingTop + valueOfDB, starX + widthOfCylinder, height - paddingBottom);
canvas.drawRect(cylinder, paint);

Здесь RectF представляет собой прямоугольную область, которая определяет диапазон, в котором кисть может рисовать пиксели. Если она выходит за пределы этого диапазона, она не действует. Чтобы улучшить визуальный эффект, необходимо оптимизировать его в соответствии с направлением, заданным LinearGradient.

Следует также отметить, что, как показано на рисунке выше, рисование начинается с левого верхнего угла View. Линейный градиент и RectF также основаны на координатах x и y относительно View. Мы хотим, чтобы столбец цвета находился внизу View, поэтому «stopY должен быть высотой View», а startY — высотой View минус высота столбца цвета.

4. Рисование шкалы

Эта часть довольно проста.

// Нарисовать линию (startX, startY, stopX, stopY, кисть)
canvas.drawLine(startX, startY, stopX, stopY, paint);

Разделите интервалы в соответствии с пропорцией и последовательно обновляйте startX и stopY. Разделите их на две стороны в соответствии с заданным эффектом. Получение ресурсов и работа с Bitmap

  1. Получение ресурсов:
  • getResources().getDrawable(R.drawable.yellow)).getBitmap();
  • bmpGreen = ((BitmapDrawable) getResources().getDrawable(R.drawable.green)).getBitmap();
  1. Масштабирование Bitmap по пропорции:
matrixRed = new Matrix();
matrixRed.postScale(50, redHeight / 10); // Горизонтальное и вертикальное масштабирование
bmp_red = Bitmap.createBitmap(bmpRed, 0, 0, 10, 10, matrixRed, true); // (Исходный Bitmap, начало обрезки x, начало обрезки y, ширина обрезки, высота обрезки)
  1. Объединение Bitmap:

Через описанные выше методы получаем три подходящих по размеру одноцветных Bitmap, затем объединяем их в один Bitmap с помощью следующего кода:

multiColorBmp = Bitmap.createBitmap(width, multiHeight, Config.ARGB_8888);
Canvas ccc = new Canvas(multiColorBmp); 
ccc.drawBitmap(bmp_red, 0, 0, null);
ccc.drawBitmap(bmp_yellow, 0, bmp_red.getHeight(), null);
ccc.drawBitmap(bmp_green, 0, bmp_yellow.getHeight() + bmp_red.getHeight(), null);

В результате multiColorBmp можно использовать для рисования столбцов цветов на капсуле.

  1. Рисование чистых цветов:

Поскольку в рамках проекта капсула и её дно должны быть изображениями, возникает вопрос, как сделать так, чтобы при рисовании столбцов цветов они отображались только в пределах заданной высоты, а остальная часть капсулы оставалась видимой.

Для этого используется новый объект PorterDuffXfermode, который предоставляет концепцию, аналогичную слоям в Photoshop:

Далее следует описание концепции и пример кода на Java:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    int sc = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);

    Rect rect = new Rect(0, 0, width, height);
    canvas.drawBitmap(bmp, rect, rect, paint); // Уже нарисованный элемент становится dst

    paint.setXfermode(mFermode);   // Режим наложения изображений

    if(null != multiColorBmp){
        canvas.drawBitmap(multiColorBmp, 0, height - multiColorBmp.getHeight(), paint);
    }
    
    paint.setXfermode(null);

    canvas.restoreToCount(sc); // Убирает чёрные границы
}

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Пользовательский контрол со значениями шкалы. Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/vigiles-UScaleView.git
git@api.gitlife.ru:oschina-mirror/vigiles-UScaleView.git
oschina-mirror
vigiles-UScaleView
vigiles-UScaleView
master