Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.71
niklep
2 / 2 / 1
Регистрация: 10.03.2010
Сообщений: 44
#1

Добавление элемента - наследника View - Программирование Android

12.11.2012, 20:12. Просмотров 1803. Ответов 10
Метки нет (Все метки)

Здравствуйте. Пишу для Android простенькую игрушку. Для нее мне понадобилось написать класс, рисующий круг - наследник View. На экране одновременно должно быть множество кругов. Но у меня проблема в том, что отображается на экране только тот круг, который я последним добавил, а предыдущие исчезают. Подскажите, где я ошибся?
Моя основная Активити:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public class GameActivity extends Activity {
 
    ...
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);
        
        // Узнаю размеры экрана.        
        getDisplayParams();
        
        ...
 
        // все объекты добавляю на RelativeLayout
        relLayout = (RelativeLayout)findViewById(R.id.relLayout);
        lpView = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        // grid - это тоже наследник View, но простой. Он просто рисует сетку и высчитывает ее размеры, размеры каждой учейки и т.п.
        grid = new Grid(getApplicationContext(), screenWidth);
        relLayout.addView(grid);
        
        // Старт игры. См. ниже
        startNewGame();
    }
 
    ...
    
    private void initCircleArrays() {
                
        // проходит инициализация служебных массивов и структур
 
    }
    
    @SuppressWarnings("deprecation")
    @TargetApi(13)
    private void getDisplayParams() {
 
        ...
 
    }
    
    // Добавление одного шарика на поле. Параметрами передаю позицию шара на поле 9x9 и его цвет
    private void addSingleCircle(int posCircleX, int posCircleY, int colorCircle) {
 
        ...
 
        // Передаю кругу информацию о его цвете
        circleArr[posCircleY-1][posCircleX-1].customColor(colorCircle);
        // Передаю кругу его позицию на поле
        circleArr[posCircleY-1][posCircleX-1].setPosition(posCircleX, posCircleY);
 
        // считаю margin слева и сверху для круга
        // getCellWidth() -  получение ширины каждой ячейки поля, getGridOffset() - смещение сетки относительно края и верха экрана (ширина сетки меньше ширины экрана, и сетка выровнена по центру. Соответственно появляется отступ. Сверху отступ такой же, как и по бокам. А вообще, смотри приложенный скриншот...)
        // posCircleX и posCircleY добавляю, чтобы в отступе учесть суммарную толщину однопиксельных линий - разделителей ячеек.
        lpView.leftMargin=(int)((posCircleX-1)*getCellWidth()+getGridOffset()+posCircleX);
        lpView.topMargin=(int)((posCircleY-1)*getCellWidth()+getGridOffset()+posCircleY);
        
        relLayout.addView(circleArr[posCircleY-1][posCircleX-1],lpView);
    }
    
    // Добавляю по 3 шара на поле в рандомные свободные ячейки.
    private void addTripleRandomCircle() {
        
        ...
        
    }
        
    ...
    
    private void startNewGame() {
        initCircleArrays();
        //addTripleRandomCircle();
        addSingleCircle(1, 1, Color.BLACK);
        addSingleCircle(2, 2, Color.BLACK);
    }
    
    public float getGridOffset() {
        return grid.getBitmapLeftAndTopPos();
    }
    
    public float getCellWidth() {
        return grid.getCellWidth();
    }
    
    ...
}
И собственно класс CircleView, рисующий круг
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class CircleView extends View {
 
    ...
    
    public CircleView(GameActivity context) {
        super(context);
        this.context=context;
        init();
    }
 
    public CircleView(GameActivity context, AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        init();
    }
    
private void init() {
        // получаем смещение сетки
    gridOffset=context.getGridOffset();
 
        // получаем ширину ячейки
    cellWidth=context.getCellWidth();   
    
        // устанавливаем кисть
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
                // размер нашей view'шки - ширина ячейки
        setMeasuredDimension((int)cellWidth, (int)cellWidth);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // рисуем круг
        canvas.drawCircle(cellWidth/2, cellWidth/2, radius, paint);
    }
    
    public void setColor(int circleColor) {
        paint.setColor(circleColor);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
             
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.d(TAG,"Position Of this circle: " + String.valueOf(this.posX) + " and " + String.valueOf(this.posY));
        }
        return true;
    }
    
    ...
 
    // оповещение шара о его местоположении на поле
    public void setPosition(int posX, int posY) {
        this.posX=posX;
        this.posY=posY;
    }
Сейчас в методе startNewGame() указано нарисовать круги в ячейках (1,1) и (2,2) (отсчет с единицы).
Но рисуется только второй. И так, какие бы координаты я не указал, рисуется всегда тот, который рисуется последним.
Миниатюры
Добавление элемента - наследника View  
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.11.2012, 20:12     Добавление элемента - наследника View
Посмотрите здесь:

Программное добавление View - Программирование Android
Доброго времени. Знаю что на эту тему много инфы, как на форуме так и на других ресурсах, но решения своей проблемы все же не нашел. суть...

Программное добавление View - Программирование Android
Всем привет! У меня в роли setContentView выступает класс Draw2D, в котором я собираюсь рисовать кое-какую графику. Графика рисуется...

Программное добавление View - Программирование Android
Не могу разобраться: нужно программно прилепить н-ное количество вьюх. Делаю так: Dialog dialog = new Dialog(pd.getContext()); ...

Добавление View (кнопки) в PreferenceScreen - Программирование Android
Здравствуйте! не получается добавить View (кнопку) в общую структуру PreferenceScreen, через this.addContentView добавляется, но...

Программное добавление View элементов в Fragment - Программирование Android
Здравствуйте. Проблема такая: в приложении есть 2 вкладки. Переключение между ними реализуются через ViewPager и FragmentStatePagerAdapter....

Добавление View в FrameLayout: ошибка в приложении - Программирование Android
Доброго времени суток! Хочу вот этот класс, который унаследован от View, добавить в уже созданный FrameLayout. Вот так не работает: ...

На какой тип Layout добавление View идёт быстрее - Программирование Android
Если я хочу разместить 3 View в Layoutе. То в каком Layoutе View разместить быстрее(ну скорость добавления View выше) в LinearLayout в...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Creative
22 / 8 / 1
Регистрация: 13.07.2012
Сообщений: 66
12.11.2012, 22:10     Добавление элемента - наследника View #2
создайте класс Circle который будет иметь поля для хранения позиции и цвета а также метод отрисовки, в главной активити создайте массив типа Circle добавляйте в него новые объекты, а в методи onDraw вашего View отрисовывайте циклом весь массив.

Добавлено через 2 минуты
Цитата Сообщение от niklep Посмотреть сообщение
И так, какие бы координаты я не указал, рисуется всегда тот, который рисуется последним.
вы просто храните данные только про один круг, вот круг с последними данными и отображается
niklep
2 / 2 / 1
Регистрация: 10.03.2010
Сообщений: 44
13.11.2012, 07:31  [ТС]     Добавление элемента - наследника View #3
Спасибо за ответ.
Наверное, я из кода здесь лишнего понаудалял. Теперь поясню:
создайте класс Circle который будет иметь поля для хранения позиции и цвета а также метод отрисовки
Мой класс CircleView имеет поля для хранения позиции и цвета:
Java
1
2
3
4
5
6
public class CircleView extends View {
    ...
    private Paint paint; // paint хранит в себе цвет
    private int posX=0;
    private int posY=0;
        ...
а также метод отрисовки и задания размеров:
Java
1
2
3
4
5
6
7
8
9
10
11
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension((int)context.getCellWidth(), (int)context.getCellWidth());
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(cellWidth/2, cellWidth/2, radius, paint);
    }
в главной активити создайте массив типа Circle добавляйте в него новые объекты
Я так и поступаю:
Java
1
2
3
public class GameActivity extends Activity {
    ...
    private CircleView[][] circleArr; // матрица хранит в себе объекты класса CircleView
При создании нового круга я сохраняю его в этой матрице:
Java
1
2
3
4
5
6
7
8
9
10
11
private void addSingleCircle(int posCircleX, int posCircleY, int colorCircle) {
        circleArr[posCircleY-1][posCircleX-1] = new CircleView(this); // !!! Создаю объект круга
        ...
        circleArr[posCircleY-1][posCircleX-1].setColor(colorCircle);
        circleArr[posCircleY-1][posCircleX-1].setPosition(posCircleX, posCircleY);
        
        lpView.leftMargin=(int)((posCircleX-1)*getCellWidth()+getGridOffset()+posCircleX); // указываю отступы
        lpView.topMargin=(int)((posCircleY-1)*getCellWidth()+getGridOffset()+posCircleY); // указываю отступы
        
        relLayout.addView(circleArr[posCircleY-1][posCircleX-1],lpView); // добавляю круг на layout
    }
а в методе onDraw вашего View отрисовывайте циклом весь массив.
Так делать обязательно? Представим, у меня 70 кругов на поле, и при добавлении 71го я должен отрисовать все 71? Ну уж нет...

вы просто храните данные только про один круг, вот круг с последними данными и отображается
Я храню данные обо всех кругах в двумерном массиве (см. выше метод addSingleCircle()), а также каждый добавляю на Layout. Где я не прав?
Creative
22 / 8 / 1
Регистрация: 13.07.2012
Сообщений: 66
13.11.2012, 12:10     Добавление элемента - наследника View #4
Да, я действительно вас не правильно понял кстати, а зачем вам матрица если вы и так координаты храните внутри объекта?

Добавлено через 2 минуты
честно говоря не могу сообразить в чем ошибка... но по мне проще было бы рисовать это все прямо на канве, я подумал сначала, что вы так и делаете, поэтому и посоветовал циклом отрисовывать.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
13.11.2012, 13:27     Добавление элемента - наследника View #5
Цитата Сообщение от niklep Посмотреть сообщение
relLayout.addView(circleArr[posCircleY-1][posCircleX-1],lpView);
ну вот, один и тот же lpView суете. где new?
Цитата Сообщение от niklep Посмотреть сообщение
...
здесь может?
niklep
2 / 2 / 1
Регистрация: 10.03.2010
Сообщений: 44
13.11.2012, 21:10  [ТС]     Добавление элемента - наследника View #6
2 Creative: Матрица мне нужна для того, чтобы в последующем обратиться к созданному кругу(мне их надо двигать).

Добавлено через 6 минут
2 V0v1k: видимо, ты нашел проблему. Спасибо. Чуть позже вечером окажусь при исходниках, проверю.
Также нашел цитату с уроков по Android:
Обратите внимание, что для двух объектов View я использовал один объект LayoutParams - lpView. И если я теперь буду менять свойства этого объекта, меняться будут оба View.
У меня, судя по всему, предыдущие объекты оказались под видимым =)

Добавлено через 5 часов 50 минут
Проверил, проблема решилась выделением для каждого экземпляра круга своего LayoutParams.
Всем спасибо!
lifestyle
Mobile Developer
232 / 228 / 4
Регистрация: 10.05.2009
Сообщений: 917
13.11.2012, 22:38     Добавление элемента - наследника View #7
Можно не накладывать новые слои а просто рисовать на текущем слое и вообще лучше использовать SurfaceView
niklep
2 / 2 / 1
Регистрация: 10.03.2010
Сообщений: 44
14.11.2012, 07:08  [ТС]     Добавление элемента - наследника View #8
2 lifestyle: Если я нарисую круги просто на канве, то мне потом придется изобретать велосипед для того, чтобы передвигать эти круги. А в виде отдельных объектов (наследников View) - можно использовать встроенные анимации.
SurfaceView мне не нужен, у меня простейшая 2D графика.
kvaka
29 / 29 / 3
Регистрация: 26.06.2012
Сообщений: 163
14.11.2012, 10:28     Добавление элемента - наследника View #9
Соглашусь с LifeStyle. С SurfaceView все было бы в разы проще. И никаких проблем с перемещением кругов не будет. Круги можете также создавать как отдельные объекты, но своего типа, а не наследники от View. Проблем с анимацией тут тоже особых не будет - перемещения объекта можно легко закодить. А так Вы реально велосипед изобретаете - как мыть пол зубной щеткой - можно, конечно, но очень долго и неудобно.
niklep
2 / 2 / 1
Регистрация: 10.03.2010
Сообщений: 44
14.11.2012, 12:05  [ТС]     Добавление элемента - наследника View #10
Хорошо, надо взглянуть на SurfaceView. Спасибо за советы.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.11.2012, 00:35     Добавление элемента - наследника View
Еще ссылки по теме:

Обработка нажатия каждого элемента List View - Программирование Android
Доброго времени суток! Нужна помощь в реализации нажатия на элемент лист вью. Необходимо присвоить каждому в списке элементу переход на...

Как обновить Recycle View после добавления нового элемента в БД? Используется Cursor - Программирование Android
Проблема такова, после добавления элемента в БД, список элементов Recycle View не обновляется, приходится заново пересоздавать фрагмент, а...

Добавление элемента в Toolbar - Программирование Android
хочу добавить один элемент в тулбар, но вместо этого в тулбаре только три точки (кнопка overflow) при нажатии на которую выпадает вариант...

Добавление элемента в список меню - Программирование Android
Вопрос наверно по конфигурированию, но хотелось бы узнать как редактировать меню отправить в окнах отправки сообщения, или через...

Добавление элемента и запись в него информации - Программирование Android
<array name="Понравившиеся"> <item>первый</item> </array> Имеется такой список в файле string. Как правильно написать код...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
lifestyle
Mobile Developer
232 / 228 / 4
Регистрация: 10.05.2009
Сообщений: 917
16.11.2012, 00:35     Добавление элемента - наследника View #11
Цитата Сообщение от niklep Посмотреть сообщение
2 lifestyle: Если я нарисую круги просто на канве, то мне потом придется изобретать велосипед для того, чтобы передвигать эти круги. А в виде отдельных объектов (наследников View) - можно использовать встроенные анимации.
SurfaceView мне не нужен, у меня простейшая 2D графика.
Это уже не 2д графика вообщето))) - это просто клепание обьектов и наращевание слоев.... интересно будет провести тест на производительность обоих вариантов)))
Yandex
Объявления
16.11.2012, 00:35     Добавление элемента - наследника View
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru