from kivy.config import Config
Config.set('graphics', 'width', '360')
Config.set('graphics', 'height', '640')
Config.set('graphics', 'resizable', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.animation import Animation
from kivy.core.window import Window
from kivy.metrics import dp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.utils import platform
Builder.load_string('''
:
orientation: 'vertical'
spacing: dp(5)
# Плашка результатов
BoxLayout:
id: result_panel
size_hint_y: None
height: 0
opacity: 0
canvas.before:
Color:
rgba: 0.2, 0.8, 0.4, 0.9
Rectangle:
pos: self.pos
size: self.size
Label:
id: result_label
text: 'Результат поиска'
color: 1, 1, 1, 1
font_size: dp(16)
bold: True
halign: 'center'
# Основная область контента с кнопками
ScrollView:
id: main_scroll
size_hint_y: 1
do_scroll_y: not search_panel.is_raised
BoxLayout:
id: content_box
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
spacing: dp(5)
padding: dp(10)
# Поисковая панель
BoxLayout:
id: search_panel
size_hint_y: None
height: dp(60)
pos_hint: {'x': 0, 'y': 0}
padding: dp(10)
spacing: dp(5)
is_raised: False
TextInput:
id: search_input
hint_text: 'Введите запрос...'
multiline: False
size_hint_x: 0.8
padding: [dp(10), (self.height - self.line_height)/2]
font_size: dp(16)
on_focus: root.on_search_focus(*args)
on_text_validate: root.do_search()
Button:
id: action_button
text: 'Добавить'
size_hint_x: 0.2
font_size: dp(13)
bold: True
background_normal: ''
background_color: (0.4, 0.6, 0.4, 1)
on_press: root.toggle_result_panel()
''')
class SearchAppUI(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Window.bind(on_keyboard=self.on_keyboard)
self.keyboard_height = dp(300)
self.create_content_buttons()
# Для Android добавляем обработчик кнопки назад
if platform == 'android':
from android.runnable import run_on_ui_thread
from jnius import autoclass
self._activity = autoclass('org.kivy.android.PythonActivity').mActivity
Window.bind(on_keyboard=self.on_keyboard)
def on_keyboard(self, window, key, *args):
if key == 27: # ESC или кнопка назад на Android
# Если поисковая панель поднята - сначала опускаем её
if self.ids.search_panel.is_raised:
self.ids.search_input.focus = False
return True
# Иначе выходим из приложения
App.get_running_app().stop()
return True
def create_content_buttons(self):
"""Создаем кнопки контента"""
content_box = self.ids.content_box
for i in range(1, 21):
btn = Button(
text=f'Кнопка {i}',
size_hint_y=None,
height=dp(50),
background_normal='',
background_color=(0.4, 0.4, 0.6, 1),
on_press=self.on_button_press
)
content_box.add_widget(btn)
def on_button_press(self, instance):
self.ids.result_label.text = f"Выбрано: {instance.text}"
if self.ids.result_panel.height == 0:
self.toggle_result_panel(show=True)
def on_search_focus(self, instance, focused):
if focused:
self.ids.search_panel.is_raised = True
Animation(
y=self.keyboard_height + dp(10),
duration=0.2,
t='out_quad'
).start(self.ids.search_panel)
Animation(
scroll_y=0,
duration=0.3
).start(self.ids.main_scroll)
else:
self.ids.search_panel.is_raised = False
Animation(
y=0,
duration=0.2,
t='out_quad'
).start(self.ids.search_panel)
def toggle_result_panel(self, show=None):
"""Переключает видимость панели результатов"""
result_panel = self.ids.result_panel
action_button = self.ids.action_button
search_input = self.ids.search_input
if show is None:
show = result_panel.height == 0
if show:
Animation(height=dp(35), opacity=1, duration=0.3).start(result_panel)
action_button.text = "Убрать"
action_button.background_color = (0.8, 0.3, 0.3, 1) # Красный цвет для "Убрать"
else:
Animation(height=0, opacity=0, duration=0.3).start(result_panel)
action_button.text = "Добавить"
action_button.background_color = (0.4, 0.6, 0.4, 1) # Зеленый цвет для "Добавить"
# Закрываем клавиатуру только если поле ввода не в фокусе
if not search_input.focus:
search_input.focus = False
def do_search(self):
"""Выполняет поиск по введенному тексту"""
query = self.ids.search_input.text.strip()
if query:
self.ids.result_label.text = f"Найдено: {query}"
if self.ids.result_panel.height == 0:
self.toggle_result_panel(show=True)
# Не снимаем фокус с поля ввода после поиска
# self.ids.search_input.focus = False
class SearchApp(App):
def build(self):
Window.clearcolor = (0.4, 0.4, 0.4, 1)
return SearchAppUI()
if __name__ == '__main__':
SearchApp().run()