Вторник, 12.12.2017, 09:16
Поиск
Никнэйм
Сертификат на никнейм Olelucoye, зарегистрирован на Тимофеев Константин Михайлович
Зарегистрируй свой никнейм
Обратная связь
olelucoye.tk@yandex.ru
Реклама AdSense
Реклама
Друзья сайта
  • Лига медицинского права
  • Гостиница "Зай"
  • FAQ по системе
  • Инструкции для uCoz
  • Главная » Статьи » Андроид разработка

    Кастомный ползунок в виде дуги (аналог SeekBar)

    В этот раз разрабатываем кастомный элемент управления в виде ползунка передвигающегося по дуге.

    Создадим стандартный проект с активити с именем ArcSeek. В проекте добавляем новый класс ArcBar с суперклассом View. Добавляем конструктор.

    public class ArcBar extends View {
           public ArcBar(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    }

    Для отрисовки нам понадобятся три объекта Path - дуга, по которой будет двигаться ползунок, дуга, которая будет показывать графически выбранное ползунком значение (от нуля до текущего значения) и сам ползунок. Нужны также будут кисти Paint и матрица для изменения положения ползунка.

    Также понадобятся целочисленные переменные для хранения размеров, размера шкалы и текущего положения ползунка. Для перемещения ползунка мы будем переопределять метод onTouchEvent, поэтому нам понадобятся две переменные типа float для хранения положения пальца на сенсоре. Забегая вперед, скажу, что для удобства в элемент управления введем опциональную функцию автоподбора высоты элемента - для этого добавим еще одну переменную - логическую. Объявляем все необходимые элементы и инициализируем графические объекты в отдельном методе init().

    public class ArcBar extends View {
        int sizeX, sizeY, centerX, centerY, offsetX;
        Paint paintArc, paintThumb, paintFill;
        int maxValue = 50;
        int curValue = 20;
        Path pathFill, pathArc, pathThumb;
        Matrix matrixThumb;
        float curX, curY;
        boolean autoHeight = false;
           
        public ArcBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
        
        private void init(){
            paintArc  = new Paint(Paint.ANTI_ALIAS_FLAG);
            paintArc.setColor(Color.BLACK);
            paintArc.setStrokeWidth(3);
            paintArc.setStyle(Paint.Style.STROKE);
            paintThumb  = new Paint(Paint.ANTI_ALIAS_FLAG);
            paintThumb.setColor(Color.BLUE);
            paintThumb.setStrokeWidth(2);
            paintThumb.setStyle(Paint.Style.FILL_AND_STROKE);
            paintFill  = new Paint(Paint.ANTI_ALIAS_FLAG);
            paintFill.setColor(Color.GREEN);
            paintFill.setStrokeWidth(7);
            paintFill.setStyle(Paint.Style.STROKE);
            pathArc = new Path();
            pathFill = new Path();
            pathThumb = new Path();
            matrixThumb = new Matrix(); 
        }
    }

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

    public void setMaxValue(int max){
            maxValue = max;
        }
        
        public void setCurValue(int cur){
            curValue = cur;
            if(cur >= maxValue)curValue = maxValue;
        }
        
        public void setAutoHeight(boolean auto){
            autoHeight = auto;
        }
        
        public int getCurValue(){
            return curValue;
        } 

    Для того чтобы определиться с размерами самого элемента и графических объектов переопределим метод onMeasure. В этот метод передаются ширина и высота элемента, которые мы установим при размещении элемента на xml-макет. Передаются они в хитром виде (складываются с одной из трех констант - для чего это - не разбирался), поэтому методом View.MeasureSpec.getSize получаем удобные для нас числа. Далее определяем эталонный размер, от которого будут плясать все остальные размеры. Определяем размеры, которые мы будем использовать при рисовании графических объектов. А также устанавливаем размеры самого элемента методом setMeasureDimension.

    Заметьте как изменяются эталонный размер и размеры элемента, в зависимости от значения флага автоподбора высоты. Для чего это нужно: в силу некоторой специфичности графической составляющей элемента идеальные размеры элемента будут такими - ширина - два радиуса дуги плюс отступы, высота - один радиус плюс отступы. При установленном значении переменной autoHeight в true размеры элемента рассчитываются так, чтобы графическая составляющая занимала всю площадь элемента. При этом в расчете участвует только, заданная xml-файле ширина, высота будет подобрана независимо от того что указано в макете.

        @Override
        protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
            int w = View.MeasureSpec.getSize(widthMeasureSpec);
            int h = View.MeasureSpec.getSize(heightMeasureSpec);
            int standart;
            if(!autoHeight){
                if(w/2 <= h - w/15){
                    standart = w;
                }else{
                    standart = h*2 - h*2/15;
                }
            }else{standart = w;}
            offsetX = standart/15;
            sizeX = standart-offsetX;
            sizeY = standart/2;
            centerX = standart/2;
            centerY = sizeY;
            if(!autoHeight){
            setMeasuredDimension(w, h);
            }else{setMeasuredDimension(w, w/2 + offsetX);}
       }

    Теперь, имея значения размеров, пишем методы  для создания графических объектов.

    private void drawingArc(){
            pathArc.reset();
            pathFill.reset();
            RectF oval = new RectF(offsetX, offsetX, sizeX, sizeY*2);
            pathArc.arcTo(oval, 180, 180);
            pathFill.arcTo(oval, 180, (float) curValue * 180/((float) maxValue));
        }
        
        private void drawingThumb(){
            float angle = (float) curValue * 180/((float) maxValue);
            matrixThumb.reset();
            matrixThumb.setRotate(angle, centerX, centerY);
            pathThumb.reset();
            pathThumb.addCircle(offsetX, sizeY, offsetX/2, Path.Direction.CW);
        }

    Небольшое графическое объяснение размеров.

    Далее переопределяем метод onDraw, в нем вызываем методы создания объектов, заканчиваем преобразования и помещаем все на Canvas.

        @Override
        protected void onDraw(Canvas canvas){
            drawingArc();
            drawingThumb();
            pathThumb.transform(matrixThumb);
            canvas.drawPath(pathArc, paintArc);
            canvas.drawPath(pathFill, paintFill);
            canvas.drawPath(pathThumb, paintThumb);
            super.onDraw(canvas);
        }

    Осталось только переопределить метод onTouchEvent, в котором будем обрабатывать перемещение ползунка.

          @Override
          public boolean onTouchEvent(MotionEvent event){
             switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    curX = event.getX();
                    curY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if((curX - event.getX()) >= (sizeX-offsetX)/maxValue){
                        curX = event.getX();
                        curValue = curValue - 1;
                        if(curValue <= 0)curValue = 0;
                        invalidate();
                    }
                    if((curX - event.getX()) <= 0-(sizeX-offsetX)/maxValue){
                        curX = event.getX();
                        curValue = curValue + 1;
                        if(curValue >= maxValue)curValue = maxValue;
                        invalidate();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    
                    break;
                }
                return true;
         }

    Готово! Переходим к макету активити, помещаем на него наш кастомный элемент, кнопку и текстовое поле. 

    В MainActivity.java в onCreate задаем параметры элемента, на кнопку вешаем изменение текста - значение, на котором находится ползунок.

    public class MainActivity extends Activity {
        ArcBar bar;
        TextView tvValue;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            bar = (ArcBar) findViewById(R.id.arcBar1);
            bar.setMaxValue(20);
            bar.setCurValue(5);
            bar.setAutoHeight(true);
            tvValue = (TextView) findViewById(R.id.tvValue);
            tvValue.setText(Integer.toString(bar.getCurValue()));
        }
        public void onClick(View v){
            tvValue.setText(Integer.toString(bar.getCurValue()));
        }
    }

    Запускаем, тестим. Чтобы лучше понять как работает автоподбор высоты, можно поиграть с параметрами width, height на макете и с методом setAutoHeight. Чтобы видны были границы элемента, нужно залить фон каким-нибудь цветом.

    Исходные коды можно посмотреть здесь.

    З.Ы. Отслеживание положения ползунка правильнее было бы реализовать с помощью интерфейса листенера. Но с интерфейсами я еще не до конца разобрался. Потому пока так.

    Анимация в Андроид.

    Кастомизация элементов управления в Андроид.

    Создание кастомного View-элемента интерфейса.

    Создание виджета-часы с кастомным шрифтом

    Программируем калькулятор на андроид. Урок 1.

    Андроид приложение - Списки.

    Пластилиновый калькулятор для Андроид.

    Клавиатура DNS KB-024BQ

    Игровая мышь A4Tech XL-750BH

    Делаем полноценное приложение на VBA часть1

    Категория: Андроид разработка | Добавил: Olelucoye (09.03.2015)
    Просмотров: 1632
    | Теги: кастомизация, элемент управления, SeekBar, java, ползунок, андроид | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Меню сайта
    Категории раздела
    Андроид разработка [23]
    libGDX [24]
    Мои андроид проекты [6]
    Excel [7]
    Железяки [5]
    Скрипты в блокноте [4]
    Разное [1]
    Форма входа
    Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Яндекс Метрика
    Яндекс.Метрика