Как обнаружить сенсорное перемещение по большому количеству просмотров? - PullRequest
0 голосов
/ 08 марта 2019

Мои требования : мне нужно анимировать 7 * 16 светодиодный дисплей, передавая кадры через приложение Android через BluetoothLE.Я создал дизайн дисплея в приложении и добавил к ним пустые виды с градиентным фоном.Цвет этих представлений должен измениться, когда мое касание перемещается в них.Добавление сенсорного прослушивателя к каждому представлению не поможет в моем случае.

Чего я достиг : у меня есть большое количество представлений (100+), добавленных программно с тегомустановить для каждого из них.Я установил обработчик событий OnTouch для родительского представления, в которое были добавлены эти представления.Отслеживая абсолютные координаты события касания (x и y) и сравнивая с абсолютными границами нескольких отдельных представлений, которые я зацикливаю в обработчике событий касания, я могу обнаруживать зависание, подобное движению касания (вне границ воценки) более 3-4 просмотров правильно.

Я сослался на решение из https://stackoverflow.com/a/21903640

Где я застрял : Однако, когда я пытаюсь увеличить размер цикла, чтобы охватить все добавленные виды,отклик приложения замедляется, и при наведении на большинство представлений происходит сбой.Я знаю, что это происходит из-за сложных вычислений в обработчике событий OnTouch, которые я не должен делать.

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

Фрагмент кода

void DrawScreen()
        {
            for (int column = 0; column < 8; column++)
            {
                for (int row = 0; row < 17; row++)
                {
                    relativeLayout.AddView(DrawRect(row, column));
                }
            }
        }

View DrawRect(int row, int column)
        {
            View customView = new View(Context);
            GradientDrawable shape = new GradientDrawable();
            shape.SetShape(ShapeType.Rectangle);
            shape.SetCornerRadii(new float[] { 10, 10, 10, 10, 10, 10, 10, 10 });
            shape.SetColor(Color.ParseColor("#3F0000"));
            RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
            param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
            param.Width = width;
            param.Height = height;
            param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
            customView.Background = shape;
            customView.LayoutParameters = param;
            customView.Tag = (8 - column).ToString() + "," + (17 - row).ToString();           
            return customView;
        }

private void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
    {
        if(e.Event.Action == MotionEventActions.Up)
        {
            out_of_bounds = true;
            view_in_bound = null;
        }
        else
        {
            for (int row = 1; row < 8; row++)
            {
                for (int column = 1; column < 17; column++)
                {
                    View view = relativeLayout.FindViewWithTag(row.ToString() + "," + column.ToString());

                    if (CheckInterSection(view, e.Event.RawX, e.Event.RawY))
                    {
                        if (out_of_bounds == true)
                        {
                            view_in_bound = view;
                            out_of_bounds = false;
                            Log.Debug("Touch", "Inside");
                            //ToggleViewState(view);                                   
                        }
                        else
                        {
                            Log.Debug("Touch", "Still Inside");
                        }
                    }
                    else
                    {
                        if (view == view_in_bound)
                        {
                            out_of_bounds = true;
                            view_in_bound = null;
                            Log.Debug("Touch", "Outside");
                        }                                
                    }
                }
            }
        }
    }

bool CheckInterSection(View view, float rawX, float rawY)
        {
            int[] location = new int[2];
            view.GetLocationOnScreen(location);           
            int x = location[0] - h_spacing/2;
            int y = location[1] - v_spacing/2;
            int width = (view.Width + h_spacing/2);
            int height = (view.Height + v_spacing/2);
            return (!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height)));
        }

1 Ответ

0 голосов
/ 28 марта 2019

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

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

void DrawScreen()
        {            
            for (int column = 1; column < 17; column++)
            {
                for (int row = 1; row < 8; row++)
                {
                    relativeLayout.AddView(DrawRect(row, column));
                }
            }
        }

View DrawRect(int row, int column)
        {
            View customView = new View(Context);
            if (!CheckBit(row - 1, column - 1))
            {
                customView.SetBackgroundResource(Resource.Drawable.off_rounded_btn);
            }
            else
            {
                customView.SetBackgroundResource(Resource.Drawable.rounded_btn);
            }
            RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
            param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
            param.Width = width;
            param.Height = height;
            param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
            customView.LayoutParameters = param;
            customView.Tag = row.ToString() + "," + column.ToString();           
            return customView;
        }

void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
        {
            if (e.Event.Action == MotionEventActions.Up)
            {
                view_in_bound = null;
            }
            else
            {
                int row = CheckTouchArea(e.Event.RawX, e.Event.RawY)[0];
                if (row != 0)
                {
                    int column = CheckTouchArea(e.Event.RawX, e.Event.RawY)[1];
                    check_view = GetView(row, column);
                    if (check_view != view_in_bound)
                    {
                        ChangeViewState(check_view, Touch_CheckBit(row - 1, column - 1), row - 1, column - 1);
                        view_in_bound = check_view;
                    }
                }   
            }
        }

int[] CheckTouchArea(float rawX, float rawY)
        {
            int[] tag = new int[2];
            int[] location = new int[2];
            relativeLayout.GetLocationOnScreen(location);
            float x = location[0] + h_padding / 2;
            int y = location[1] + v_padding / 2;
            float width = relativeLayout.Width - h_padding;
            int height = relativeLayout.Height - v_padding;
            if ((!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height))))
            {
                int column = (int)Math.Ceiling((rawX - x) * 16 / width);
                int row = (int)(Math.Ceiling((rawY - y) * 7 / height));
                tag[0] = row;
                tag[1] = column;
            }            
            return tag;
        }  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...