Привет! В прошлой статье мы научились обрабатывать сообщения и команды. Теперь пришло время научиться создавать удобный интерфейс для пользователя — клавиатуры. Они делают взаимодействие с ботом проще и быстрее.
В этой статье мы разберём:
- ReplyKeyboardMarkup — обычная клавиатура
- InlineKeyboardMarkup — инлайн-клавиатура
- Создание кнопок и обработка нажатий
- Что нужно знать перед началом
- Основная часть
- ReplyKeyboardMarkup (обычная клавиатура)
- ReplyKeyboardMarkup с несколькими строками
- InlineKeyboardMarkup (инлайн-клавиатура)
- Inline-клавиатура с несколькими кнопками
- Динамическое создание клавиатур
- Редактирование сообщений с клавиатурой
- Пример из реальной жизни
- Задачи для закрепления
- Нюансы и подводные камни
- Reply-клавиатура остаётся на месте
- Inline-клавиатура привязана к сообщению
- Обработка callback-запросов
- Частые ошибки и как их избежать
- Ошибка 1: Неправильный импорт
- Ошибка 2: Забыл callback.answer()
- Ошибка 3: Неправильный callback_data
- Шпаргалка
- Заключение / Выводы
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный aiogram (статья 2)
- Базовое понимание обработчиков (статья 3)
Совет: Клавиатуры делают ботов удобнее. Пользователь может просто нажать кнопку, а не вводить команды вручную.
Основная часть
ReplyKeyboardMarkup (обычная клавиатура)
Reply-клавиатура заменяет стандартную клавиатуру в Telegram. Она привязана к чату и остаётся на месте, пока не будет скрыта.
Импорт:
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemoveСоздание клавиатуры:
# Простая клавиатура с двумя кнопками
keyboard = ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="Привет")],
[KeyboardButton(text="Помощь")]
],
resize_keyboard=True,
input_field_placeholder="Выберите действие"
)Отправка клавиатуры:
@dp.message(Command("start"))
async def start_command(message: types.Message):
await message.answer("Выберите действие:", reply_markup=keyboard)Обработка нажатий:
@dp.message(Text("Привет"))
async def hello_handler(message: types.Message):
await message.answer("Привет! Как дела?")
@dp.message(Text("Помощь"))
async def help_handler(message: types.Message):
await message.answer("Я бот. Напиши /start, чтобы начать.")Удаление клавиатуры:
@dp.message(Command("hide"))
async def hide_keyboard(message: types.Message):
await message.answer("Клавиатура скрыта", reply_markup=ReplyKeyboardRemove())ReplyKeyboardMarkup с несколькими строками
keyboard = ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="Курс USD"), KeyboardButton(text="Курс EUR")],
[KeyboardButton(text="Погода"), KeyboardButton(text="Новости")]
],
resize_keyboard=True,
one_time_keyboard=False,
input_field_placeholder="Выберите пункт меню"
)| Параметр | Что делает |
|---|---|
resize_keyboard=True | Подгоняет размер кнопок |
one_time_keyboard=False | Клавиатура не исчезает после нажатия |
input_field_placeholder | Подсказка в поле ввода |
InlineKeyboardMarkup (инлайн-клавиатура)
Инлайн-клавиатура появляется под сообщением и привязана к нему. Кнопки отправляют callback-запросы.
Импорт:
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.filters import TextСоздание inline-клавиатуры:
# Простая инлайн-клавиатура с одной кнопкой
inline_keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="Нажми меня", callback_data="button_click")]
]
)Отправка inline-клавиатуры:
@dp.message(Command("inline"))
async def inline_command(message: types.Message):
await message.answer("Нажми на кнопку", reply_markup=inline_keyboard)Обработка callback-запросов:
@dp.callback_query(Text("button_click"))
async def button_callback(callback: types.CallbackQuery):
await callback.answer("Кнопка нажата!")
await callback.message.edit_text("Спасибо за нажатие!")Inline-клавиатура с несколькими кнопками
inline_keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="Да", callback_data="yes"),
InlineKeyboardButton(text="Нет", callback_data="no")],
[InlineKeyboardButton(text="Справка", callback_data="help")]
]
)Обработка нескольких callback-запросов:
@dp.callback_query(Text("yes"))
async def yes_callback(callback: types.CallbackQuery):
await callback.answer("Вы выбрали ДА")
await callback.message.edit_text("Отлично! Вы согласились.")
@dp.callback_query(Text("no"))
async def no_callback(callback: types.CallbackQuery):
await callback.answer("Вы выбрали НЕТ")
await callback.message.edit_text("Вы не согласились.")
@dp.callback_query(Text("help"))
async def help_callback(callback: types.CallbackQuery):
await callback.answer("Справка")
await callback.message.edit_text("Это простая Inline-клавиатура.")Динамическое создание клавиатур
def create_keyboard(items):
keyboard = InlineKeyboardMarkup(inline_keyboard=[])
for item in items:
button = InlineKeyboardButton(text=item, callback_data=item)
keyboard.inline_keyboard.append()
return keyboard
items = ["Пункт 1", "Пункт 2", "Пункт 3"]
keyboard = create_keyboard(items)
@dp.message(Command("menu"))
async def menu_command(message: types.Message):
await message.answer("Выберите пункт:", reply_markup=keyboard)
Редактирование сообщений с клавиатурой
@dp.callback_query(Text("page_1"))
async def page1_callback(callback: types.CallbackQuery):
await callback.answer("Переход на страницу 1")
await callback.message.edit_text("Это страница 1", reply_markup=inline_keyboard_page2)
@dp.callback_query(Text("page_2"))
async def page2_callback(callback: types.CallbackQuery):
await callback.answer("Переход на страницу 2")
await callback.message.edit_text("Это страница 2", reply_markup=inline_keyboard_page1)Пример из реальной жизни
Меню ресторана:
# Создание клавиатуры
food_keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="Пицца", callback_data="pizza"),
InlineKeyboardButton(text="Суши", callback_data="sushi")],
[InlineKeyboardButton(text="Паста", callback_data="pasta"),
InlineKeyboardButton(text="Заказать", callback_data="order")]
]
)
@dp.message(Command("menu"))
async def menu_command(message: types.Message):
await message.answer("Меню ресторана:", reply_markup=food_keyboard)
@dp.callback_query(Text("pizza"))
async def pizza_callback(callback: types.CallbackQuery):
await callback.answer("Пицца выбрана")
await callback.message.edit_text("Вы выбрали пиццу. Добавить в корзину?", reply_markup=confirm_keyboard)
@dp.callback_query(Text("order"))
async def order_callback(callback: types.CallbackQuery):
await callback.answer("Заказ оформлен")
await callback.message.edit_text("Ваш заказ принят! Ожидайте доставку.")Задачи для закрепления
Задача 1. Создай Reply-клавиатуру с кнопками «Да» и «Нет».
Задача 2. Создай Inline-клавиатуру с кнопкой «Нажми меня».
Задача 3. Обработай callback «yes» и отправь сообщение «Вы выбрали Да».
Задача 4. Создай Reply-клавиатуру с несколькими строками.
Задача 5. В чём разница между Reply и Inline клавиатурами?
Ответы:
Задача 1.
keyboard = ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="Да"), KeyboardButton(text="Нет")]
],
resize_keyboard=True
)
Задача 2.
inline_keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="Нажми меня", callback_data="click")]
]
)Задача 3.
@dp.callback_query(Text("yes"))
async def yes_callback(callback: types.CallbackQuery):
await callback.answer("Вы выбрали Да")
await callback.message.edit_text("Вы выбрали Да")Задача 4.
keyboard = ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="Пункт 1"), KeyboardButton(text="Пункт 2")],
[KeyboardButton(text="Пункт 3"), KeyboardButton(text="Пункт 4")]
],
resize_keyboard=True
)
Задача 5.
# ReplyKeyboardMarkup — обычная клавиатура в чате
# InlineKeyboardMarkup — клавиатура под сообщением с callback-запросамиНюансы и подводные камни
Reply-клавиатура остаётся на месте
Reply-клавиатура остаётся в чате, пока не будет скрыта командой ReplyKeyboardRemove().
Inline-клавиатура привязана к сообщению
Inline-клавиатура привязана к конкретному сообщению и появляется только под ним.
Обработка callback-запросов
Все callback-запросы обрабатываются через @dp.callback_query().
Частые ошибки и как их избежать
Ошибка 1: Неправильный импорт
Импортируй ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton.
Ошибка 2: Забыл callback.answer()
Всегда используй callback.answer() для подтверждения нажатия.
Ошибка 3: Неправильный callback_data
Callback-данные должны быть строками, и они должны совпадать с фильтром.
Шпаргалка
| Тип клавиатуры | Импорт |
|---|---|
| Reply | ReplyKeyboardMarkup, KeyboardButton |
| Inline | InlineKeyboardMarkup, InlineKeyboardButton |
| Удалить Reply | ReplyKeyboardRemove() |
| Обработать callback | @dp.callback_query(Text("data")) |
Заключение / Выводы
Сегодня мы:
- Научились создавать ReplyKeyboardMarkup
- Научились создавать InlineKeyboardMarkup
- Обрабатывать callback-запросы
- Создавать интерактивные меню








