Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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.uix.widget import Widget
- from kivy.uix.behaviors import ButtonBehavior
- from kivy.uix.label import Label
- from kivy.uix.modalview import ModalView
- from kivy.properties import StringProperty, NumericProperty
- from kivy.utils import platform
- from kivy.clock import Clock
- Builder.load_string('''
- <ClickableOverlay>:
- canvas:
- Color:
- rgba: 0, 0, 0, 0.3 if self.active else 0
- Rectangle:
- pos: self.pos
- size: self.size
- <ContentItem>:
- orientation: 'horizontal'
- size_hint_y: None
- height: dp(50)
- spacing: dp(5)
- padding: dp(5)
- canvas.before:
- Color:
- rgba: 0.4, 0.4, 0.6, 1
- Rectangle:
- pos: self.pos
- size: self.size
- Label:
- id: title_label
- text: root.item_title
- size_hint_x: 0.8
- halign: 'left'
- valign: 'middle'
- text_size: self.width, None
- color: 1, 1, 1, 1
- font_size: dp(16)
- bold: True
- Button:
- id: info_button
- text: 'i'
- size_hint_x: 0.2
- size_hint_y: 1
- background_normal: ''
- background_color: 0.8, 0.8, 0.2, 1
- font_size: dp(14)
- bold: True
- on_press: root.show_info()
- <InfoDialog>:
- size_hint: (0.8, 0.8)
- auto_dismiss: True
- BoxLayout:
- orientation: 'vertical'
- padding: dp(20)
- spacing: dp(10)
- canvas.before:
- Color:
- rgba: 0.3, 0.3, 0.5, 1
- Rectangle:
- pos: self.pos
- size: self.size
- Label:
- text: root.title
- font_size: dp(20)
- bold: True
- color: 1, 1, 1, 1
- size_hint_y: 0.3
- Label:
- text: root.description
- font_size: dp(16)
- color: 1, 1, 1, 1
- text_size: self.width, None
- valign: 'top'
- halign: 'left'
- size_hint_y: 0.7
- Button:
- text: 'Close'
- size_hint_y: 0.2
- background_normal: ''
- background_color: 0.8, 0.3, 0.3, 1
- on_press: root.dismiss()
- <SearchApplicationUI>:
- orientation: 'vertical'
- spacing: dp(5)
- padding: [0, 0, 0, root.keyboard_padding]
- BoxLayout:
- id: notification_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: notification_label
- text: ''
- color: 1, 1, 1, 1
- font_size: dp(18)
- bold: True
- halign: 'center'
- padding: [dp(10), dp(5)]
- ScrollView:
- id: content_scroll
- size_hint_y: 1
- do_scroll_y: True
- BoxLayout:
- id: items_container
- orientation: 'vertical'
- size_hint_y: None
- height: self.minimum_height
- spacing: dp(5)
- padding: [dp(10), dp(0)]
- BoxLayout:
- id: search_controls
- size_hint_y: None
- height: dp(60)
- padding: dp(10)
- spacing: dp(5)
- TextInput:
- id: search_field
- hint_text: 'Enter search query...'
- 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_changed(*args)
- on_text_validate: root.perform_search()
- Button:
- id: action_btn
- text: 'Add'
- 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_notification_panel()
- ClickableOverlay:
- id: keyboard_dismiss_area
- size_hint: (1, 1)
- active: False
- on_press:
- root.hide_virtual_keyboard()
- self.active = False
- ''')
- class ClickableOverlay(ButtonBehavior, Widget):
- active = False
- class InfoDialog(ModalView):
- title = StringProperty('')
- description = StringProperty('')
- class ContentItem(ButtonBehavior, BoxLayout):
- item_title = StringProperty('')
- item_description = StringProperty('')
- def __init__(self, item_title="", item_description="", **kwargs):
- super().__init__(**kwargs)
- self.item_title = item_title
- self.item_description = item_description
- def on_press(self):
- app = App.get_running_app()
- app.root.ids.notification_label.text = f"Selected: {self.item_title}"
- if app.root.ids.notification_panel.height == 0:
- app.root.show_notification_panel()
- def show_info(self):
- dialog = InfoDialog(title=self.item_title,
- description=self.item_description)
- dialog.open()
- class SearchApplicationUI(BoxLayout):
- keyboard_height = NumericProperty(0)
- keyboard_padding = NumericProperty(0)
- def __init__(self, **kwargs):
- super().__init__(**kwargs)
- self._keyboard_listener = None
- self._keyboard_measured = False
- Window.bind(on_keyboard=self._on_keyboard)
- # Для Android настраиваем слушатель клавиатуры
- if platform == 'android':
- Clock.schedule_once(self._setup_keyboard_listener, 0.5)
- self.initialize_content()
- Window.clearcolor = (0.4, 0.4, 0.4, 1)
- def _setup_keyboard_listener(self, dt):
- """Установка слушателя клавиатуры для Android"""
- try:
- from android.runnable import run_on_ui_thread
- from jnius import autoclass
- @run_on_ui_thread
- def attach_listener():
- View = autoclass('android.view.View')
- root_view = Window._get_activity().getWindow().getDecorView()
- root_view.getViewTreeObserver().addOnGlobalLayoutListener(
- KeyboardListener(self))
- attach_listener()
- except Exception as e:
- print(f"Error setting up keyboard listener: {e}")
- def _on_keyboard(self, window, key, *args):
- """Обработка аппаратной клавиатуры"""
- if key == 27: # ESC key
- self.hide_virtual_keyboard()
- return True
- return False
- def on_search_focus_changed(self, instance, has_focus):
- """Измеряем высоту клавиатуры при фокусе"""
- if has_focus:
- if platform == 'android':
- Clock.schedule_once(self._measure_keyboard_height, 0.3)
- self.ids.keyboard_dismiss_area.active = True
- else:
- self.ids.keyboard_dismiss_area.active = False
- def _measure_keyboard_height(self, dt):
- """Точное измерение высоты клавиатуры"""
- try:
- input_field = self.ids.search_field
- pos = input_field.to_window(*input_field.pos)
- # Вычисляем видимую высоту над клавиатурой
- visible_height = pos[1] + input_field.height
- self.keyboard_height = max(0, Window.height - visible_height)
- # Обновляем отступ и показываем результат
- self.keyboard_padding = self.keyboard_height
- self.ids.notification_label.text = f"Keyboard: {self.keyboard_height:.1f}px"
- self.show_notification_panel()
- # Прокручиваем к полю ввода
- Clock.schedule_once(lambda dt: self.ids.content_scroll.scroll_to(input_field), 0.1)
- except Exception as e:
- print(f"Keyboard measurement error: {e}")
- def hide_virtual_keyboard(self):
- """Скрываем виртуальную клавиатуру"""
- self.ids.search_field.focus = False
- self.keyboard_padding = 0
- def initialize_content(self):
- """Заполняем контент"""
- for i in range(1, 21):
- item = ContentItem(
- item_title=f'Item {i}',
- item_description=f'Detailed description for item {i}.'
- )
- self.ids.items_container.add_widget(item)
- def toggle_notification_panel(self):
- """Переключаем панель уведомлений"""
- if self.ids.notification_panel.height == 0:
- query = self.ids.search_field.text.strip()
- if query:
- self.ids.notification_label.text = f"Added: {query}"
- self.show_notification_panel()
- else:
- self.hide_notification_panel()
- def show_notification_panel(self):
- """Показываем панель уведомлений"""
- Animation(height=dp(50), opacity=1, duration=0.3).start(self.ids.notification_panel)
- self.ids.action_btn.text = "Remove"
- self.ids.action_btn.background_color = (0.8, 0.3, 0.3, 1)
- def hide_notification_panel(self):
- """Скрываем панель уведомлений"""
- Animation(height=0, opacity=0, duration=0.3).start(self.ids.notification_panel)
- self.ids.action_btn.text = "Add"
- self.ids.action_btn.background_color = (0.4, 0.6, 0.4, 1)
- def perform_search(self):
- """Выполняем поиск"""
- query = self.ids.search_field.text.strip()
- if query:
- self.ids.notification_label.text = f"Found: {query}"
- if self.ids.notification_panel.height == 0:
- self.show_notification_panel()
- # Класс для слушателя клавиатуры Android
- if platform == 'android':
- from jnius import PythonJavaClass, java_method
- class KeyboardListener(PythonJavaClass):
- __javainterfaces__ = ['android/view/ViewTreeObserver$OnGlobalLayoutListener']
- __javacontext__ = 'app'
- def __init__(self, root_widget):
- super().__init__()
- self.root_widget = root_widget
- @java_method('()V')
- def onGlobalLayout(self):
- Clock.schedule_once(lambda dt: self.root_widget._measure_keyboard_height(dt), 0)
- class SearchApplication(App):
- def build(self):
- return SearchApplicationUI()
- if __name__ == '__main__':
- SearchApplication().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement