Форум программистов, компьютерный форум, киберфорум
Наши страницы
Программирование Android
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
sanek819
2 / 2 / 0
Регистрация: 15.06.2010
Сообщений: 13
1

Создание элементов интерфейса в Java коде

08.08.2013, 12:52. Просмотров 1473. Ответов 4
Метки нет (Все метки)

Здравствуйте! У меня есть класс PuzzleView, реализующий собственный View. В верхней части экрана рисуется квадрат, а под этим квадратом мне нужно разместить три кнопки. Пробовал создавать xml разметку, а потом использовать ее в коде, но тут возникала проблема: findViewById(R.layout.game_layout) всегда возвращал null. Пробовал создавать кнопки непосредственно в коде, но это тоже не помогло. Во всех случаях выскакивало NullPointerException. Подскажите пожалуйста, как лучше поступить в данной ситуации. Вообще учусь по книге "Привет, Андроид!", а там рассматривается пример игры судоку. Вот у меня и появились собственные идеи. Вот код PuzzleView без внесенных изменений
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package org.example.sudoku;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.graphics.Bitmap;
 
public class PuzzleView extends View
{
    private static final String TAG = "Sudoku";
    private final Game game;
    private float width; //Ширина одного тайла
    private float height; //Высота одного тайла
    private int selX; //Координата х выделенной области
    private int selY; //Координата у выделенной области
    private final Rect selRect = new Rect();
    private final Bitmap origField = BitmapFactory.decodeResource(getResources(), R.drawable.background_field);
 
    public PuzzleView(Context context)
    {
        super(context);
        this.game = (Game)context; //Сохраняем ссылку на класс Game
        setFocusable(true); //Устанавливаем параметр, позволяющий пользователю осуществить ввод данных во вьювер
        setFocusableInTouchMode(true);
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) //Вычисление размера каждого тайла
    {
        if(w <= h)
        {
            width = w/9f;
            height = w/9f;
        }
        else
        {
            width = h/9f;
            height = h/9f;
        }
        getRect(selX,selY,selRect);
        Log.d(TAG, "onSizeChanged: width" + width + ", height" + height);
        super.onSizeChanged(w, h, oldw, oldh);
    }
    
    private void getRect(int x, int y, Rect rect)
    {
        rect.set((int)(x*width),(int)(y*height), (int)(x*width+width), (int)(y*height+height));
    }
    
    protected void onDraw(Canvas canvas) //Рисование на холсте(canvas)
    {
        //Рисование фона
        Paint background = new Paint();
        Bitmap field; //Квадратный фон по размеру экрана
        //Рисуем квадрат игрового поля, фон из файла
        if(getWidth() <= getHeight())
            field = Bitmap.createScaledBitmap(origField,getWidth(), getWidth(), false);
        else
            field = Bitmap.createScaledBitmap(origField,getWidth(), getWidth(), false);
        background.setColor(Color.argb(100, 33, 178, 13));
        canvas.drawRect(0, 0, getWidth(), getHeight(), background);
        canvas.drawBitmap(field, 0, 0, background);
        //Рисование чисел
        //Определение цвета и стиля для чисел
        Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
        foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
        foreground.setStyle(Style.FILL);
        foreground.setTextSize(height*0.75f);
        foreground.setTextScaleX(width/height);
        foreground.setTextAlign(Paint.Align.CENTER);
        //Рисование числа в центре тайла
        FontMetrics fm = foreground.getFontMetrics();
        //Центровка по оси Х: использование выравнивания (и координаты центральной точки)
        float x = width/2;
        //Центровка по оси У: сначала измеряем повышение\понижение(базовая линия буквы это линия под буквой)
        float y = height/2 - (fm.ascent + fm.descent)/2;
        for(int i = 0;i < 9;i++)
            for(int j = 0;j < 9;j++)
            {
                //getTileString() нужен для того, чтобы понять, какое число писать
                canvas.drawText(this.game.getTileString(i,j), i*width+x, j*height+y, foreground);
            }
        if(Prefs.getHints(getContext())) //Если включены подсказки
        {
            //Рисование подсказок
            //Выбрать цвет подсказки, основываясь на колличестве оставшихся ходов
            Paint hint = new Paint();
            int c[] = {getResources().getColor(R.color.puzzle_hint_0),
                       getResources().getColor(R.color.puzzle_hint_1),
                       getResources().getColor(R.color.puzzle_hint_2)};
            Rect r = new Rect();
            for(int i = 0; i < 9;i++)
                for(int j = 0;j < 9;j++)
                {
                    int movesleft = 9 - game.getUsedTiles(i, j).length;
                    if(movesleft < c.length)
                    {
                        getRect(i, j, r);
                        hint.setColor(c[movesleft]);
                        canvas.drawRect(r, hint);
                    }
                }
        }
        //Рисование выделения
        Log.d(TAG, "selRect=" + selRect);
        Paint selected = new Paint();
        selected.setColor(getResources().getColor(R.color.puzzle_selected));
        canvas.drawRect(selRect, selected);
    }
    
    //Реализация способа перемещения выделения
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        Log.d(TAG, "onKeyDown: keycode=" + keyCode + ", event=" + event);
        switch(keyCode)
        {
        case KeyEvent.KEYCODE_DPAD_UP:
            select(selX, selY-1);
            break;
        case KeyEvent.KEYCODE_DPAD_DOWN:
            select(selX,selY+1);
            break;
        case KeyEvent.KEYCODE_DPAD_LEFT:
            select(selX-1,selY);
            break;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            select(selX+1,selY);
            break;
        case KeyEvent.KEYCODE_0:
        case KeyEvent.KEYCODE_SPACE:
            setSelectedTile(0);
            break;
        case KeyEvent.KEYCODE_1:
            setSelectedTile(1);
            break;
        case KeyEvent.KEYCODE_2:
            setSelectedTile(2);
            break;
        case KeyEvent.KEYCODE_3:
            setSelectedTile(3);
            break;
        case KeyEvent.KEYCODE_4:
            setSelectedTile(4);
            break;
        case KeyEvent.KEYCODE_5:
            setSelectedTile(5);
            break;
        case KeyEvent.KEYCODE_6:
            setSelectedTile(6);
            break;
        case KeyEvent.KEYCODE_7:
            setSelectedTile(7);
            break;
        case KeyEvent.KEYCODE_8:
            setSelectedTile(8);
            break;
        case KeyEvent.KEYCODE_9:
            setSelectedTile(9);
            break;
        case KeyEvent.KEYCODE_ENTER:
        case KeyEvent.KEYCODE_DPAD_CENTER:
            game.showKeypadOrError(selX, selY);
            break;
        default: 
            return super.onKeyDown(keyCode, event);
        }
        return true;
    }
    
    //Вычисление новых координат х и у выделения
    private void select(int x, int y)
    {
        invalidate(selRect); //Помечаем область как грязную(недействительную), чтобы перерисовать
        selX = Math.min(Math.max(x, 0), 8);
        selY = Math.min(Math.max(y, 0), 8);
        getRect(selX, selY, selRect);
        invalidate(selRect);
    }
    
    //Вывод на эран клавиатуры для тач скринов
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        if(event.getAction() != MotionEvent.ACTION_DOWN)
            return super.onTouchEvent(event);
        //Если касание в области квадрата, то вызываем экранную клавиатуру
        if(event.getX() <= width*9 && event.getY() <= height*9)
        {
            select((int)(event.getX()/width), (int)(event.getY()/height));
            game.showKeypadOrError(selX, selY);
            Log.d(TAG, "onTouchEvent: x" + selX + ", y " + selY);
            return true;
        }
        else
            return false;
    }
    
    public void setSelectedTile(int tile)
    {
        if(game.setTileIfValid(selX, selY, tile))
            //Помечаем весь экран как недействительный
            invalidate();
        else
        {
            //Число не подходит для этого тайла
            Log.d(TAG, "setSelectedTile: invalid" + tile);
            startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake));
        }
    }
}
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.08.2013, 12:52
Ответы с готовыми решениями:

Динамическое создание элементов интерфейса
Здравствуйте. Есть небольшая проблема с динамическим созданием элементов интерфейса. Не понимаю как...

Динамическое создание элементов интерфейса
Здравствуйте. Мне интересно знать, как динамически создавать элементы интерфейса. Например, в...

Динамическое создание элементов интерфейса
Только недавно начал изучать сишарп. Необходимо создать кнопку, которая создает лабел, при нажатии...

Динамическое создание элементов интерфейса
С Новым Годом, друзья. В общем, печалька у меня: создаю элементы, а в обработчиках события не знаю...

Динамическое создание элементов интерфейса.
Хотелось бы создавать кнопочки и др. элементы в аплете динамически, читая информацию из...

4
Yushka
4 / 4 / 0
Регистрация: 24.07.2013
Сообщений: 80
08.08.2013, 15:20 2
Мне кажется из-за отсутствия Activity.. Ваш класс наследуется от View, наверное, его нужно использовать в классе-наследнике Activity, в котором уже отображать кнопки. Хотя могу и ошибаться, сама не сталкивалась пока с кастомными View.
0
sanek819
2 / 2 / 0
Регистрация: 15.06.2010
Сообщений: 13
08.08.2013, 15:48  [ТС] 3
Да, конечно он используется в классе наследнике Activity
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Game extends Activity 
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        puzzleView = new PuzzleView(this);
        setContentView(puzzleView);
        puzzleView.requestFocus();
                //...
        }
//...
}
Вот я и хочу добавить кнопки в самом PuzzleView, а потом его использовать в Game.
Попробовал пойти другим путем:
Создал xml разметку game_layout, на которой разместил три ImageButton. Потом создал класс
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ToolbarFrame extends LinearLayout
{
 
    private ImageButton hintButton;
    private ImageButton checkButton;
    private ImageButton mainButton;
    
    public ToolbarFrame(Context context)
    {
        super(context);
        initComponents();
    }
    
    private void initComponents()
    {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.game_layout, this);
        hintButton = (ImageButton) findViewById(R.id.imageButton1);
        checkButton = (ImageButton) findViewById(R.id.imageButton2);
        mainButton = (ImageButton) findViewById(R.id.imageButton3);
    }
 
}
Теперь PuzzleView наследуется от LinearLayout
Java
1
public class PuzzleView extends LinearLayout
После этого изменил onCreate в Game
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        puzzleView = new PuzzleView(this);
        
        ToolbarFrame frame = new ToolbarFrame(getApplicationContext());
        frame.setBackgroundColor(R.color.transparent_color);
        frame.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        puzzleView.addView(frame);
        
        setContentView(puzzleView); //Установка нового содержимого для вьювера
        puzzleView.requestFocus();
Теперь ошибок нет, и game_layout отображается корректно, вот только сам PuzzleView не отображается. Что с этим можно сделать?
0
Yushka
4 / 4 / 0
Регистрация: 24.07.2013
Сообщений: 80
08.08.2013, 15:56 4
Не уверена, что это хорошо) Но я бы сделала PuzzleView наследником фрагмента, прописала бы фрагмент в xml основного класса ну и отображала бы как фрагмент. Но, возможно, что это неправильно, а может даже и не получится вдобавок. Но я бы попробовала=).
0
V0v1k
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
08.08.2013, 19:29 5
Цитата Сообщение от sanek819 Посмотреть сообщение
findViewById(R.layout.game_layout)
Java
1
findViewById(R.id.game_layout);
0
08.08.2013, 19:29
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.08.2013, 19:29

Создание элементов интерфейса по данным из БД
Здравствуйте. Вопрос в следующем: есть приложение, есть база данных, условно в базе данных в нужной...

Создание java классов в коде С++ и вызов Java методов и классов из C++
Здравствуйте! Собственно проблема вот в чем при клмпиляции получаю ошибки Первый этап обработки...

Прямоугольная матрица,сумма элементов,Создание интерфейса
Есть программа создающая матрицу и считающая сумму, минимум и максимум const nmax=100; var...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

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