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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
sanek819
2 / 2 / 0
Регистрация: 15.06.2010
Сообщений: 13
#1

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

08.08.2013, 12:52. Просмотров 1199. Ответов 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));
        }
    }
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.08.2013, 12:52     Создание элементов интерфейса в Java коде
Посмотрите здесь:

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

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

Создание интерфейса - Программирование Android
Привет всем. Я совсем недавно решил заняться разработкой под android. С одной стороны очень легко далась java, с учетом того, что на...

Динамическое создание интерфейса - Программирование Android
Уважаемые форумчане, не подскажите как можно реализовать создание интерфейса в активити по переданному приложению xml-файлу, чтобы...

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

Динамическое создание интерфейса - Программирование Android
Здравствуйте уважаемые. Помогите справиться с задачей. Хочу динамически создать несколько LinearLayout c TextView, ImageView и Button...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Yushka
4 / 4 / 1
Регистрация: 24.07.2013
Сообщений: 80
08.08.2013, 15:20     Создание элементов интерфейса в Java коде #2
Мне кажется из-за отсутствия Activity.. Ваш класс наследуется от View, наверное, его нужно использовать в классе-наследнике Activity, в котором уже отображать кнопки. Хотя могу и ошибаться, сама не сталкивалась пока с кастомными View.
sanek819
2 / 2 / 0
Регистрация: 15.06.2010
Сообщений: 13
08.08.2013, 15:48  [ТС]     Создание элементов интерфейса в Java коде #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 не отображается. Что с этим можно сделать?
Yushka
4 / 4 / 1
Регистрация: 24.07.2013
Сообщений: 80
08.08.2013, 15:56     Создание элементов интерфейса в Java коде #4
Не уверена, что это хорошо) Но я бы сделала PuzzleView наследником фрагмента, прописала бы фрагмент в xml основного класса ну и отображала бы как фрагмент. Но, возможно, что это неправильно, а может даже и не получится вдобавок. Но я бы попробовала=).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.08.2013, 19:29     Создание элементов интерфейса в Java коде
Еще ссылки по теме:

Создание интерфейса на основе макета Photoshop - Программирование Android
Я только начинаю программировать под андроид. Возникли некоторые сложности с версткой,а точнее - адаптацией под разные размеры экранов. ...

С/С++ класс в java коде - Программирование Android
А как вызывать в java коде класс определенный в jni. Ну хедер его и реализация будут в папке jni написанные на с++ а как дальше создать его...

Наложение элементов интерфейса - Программирование Android
Вопрос вот в чем: можно ли расположить элементы интерфейса, чтобы их области пересекались? Например можно ли расположить пару кнопок...

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

Создание экземпляра класса C++ в Java - Программирование Android
Здравствуйте! Подскажите, возможно ли создать экземпляр класса C++ в Java? Если да, то как? Если можно то пример с кодом C++ класса и...

Создание приложения на Java в среде разработки android studio - Программирование Android
как создать простое приложение на Java в android studio ? - не для планшета телефона или часов. для Windows скажем так. кто в android...


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

Или воспользуйтесь поиском по форуму:
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
08.08.2013, 19:29     Создание элементов интерфейса в Java коде #5
Цитата Сообщение от sanek819 Посмотреть сообщение
findViewById(R.layout.game_layout)
Java
1
findViewById(R.id.game_layout);
Yandex
Объявления
08.08.2013, 19:29     Создание элементов интерфейса в Java коде
Ответ Создать тему
Опции темы

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