Advertisement
soulseb

poisk_v1

Jun 11th, 2025 (edited)
850
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.24 KB | None | 0 0
  1. from kivy.config import Config
  2. Config.set('graphics', 'width', '360')
  3. Config.set('graphics', 'height', '640')
  4. Config.set('graphics', 'resizable', '0')
  5.  
  6. from kivy.app import App
  7. from kivy.lang import Builder
  8. from kivy.animation import Animation
  9. from kivy.core.window import Window
  10. from kivy.metrics import dp
  11. from kivy.uix.boxlayout import BoxLayout
  12. from kivy.uix.button import Button
  13. from kivy.uix.widget import Widget
  14. from kivy.uix.behaviors import ButtonBehavior
  15. from kivy.uix.label import Label
  16. from kivy.uix.modalview import ModalView
  17. from kivy.properties import StringProperty
  18. from kivy.utils import platform
  19. from kivy.clock import Clock
  20.  
  21. Builder.load_string('''
  22. <ClickableOverlay>:
  23.    canvas:
  24.        Color:
  25.            rgba: 0, 0, 0, 0
  26.        Rectangle:
  27.            pos: self.pos
  28.            size: self.size
  29.  
  30. <ContentItem>:
  31.    orientation: 'horizontal'
  32.    size_hint_y: None
  33.    height: dp(50)
  34.    spacing: dp(5)
  35.    padding: dp(5)
  36.    canvas.before:
  37.        Color:
  38.            rgba: 0.4, 0.4, 0.6, 1
  39.        Rectangle:
  40.            pos: self.pos
  41.            size: self.size
  42.    
  43.    Label:
  44.        id: title_label
  45.        text: root.item_title
  46.        size_hint_x: 0.8
  47.        halign: 'left'
  48.        valign: 'middle'
  49.        text_size: self.width, None
  50.        color: 1, 1, 1, 1
  51.        font_size: dp(16)
  52.        bold: True
  53.    
  54.    Button:
  55.        id: info_button
  56.        text: 'i'
  57.        size_hint_x: 0.2
  58.        size_hint_y: 1
  59.        background_normal: ''
  60.        background_color: 0.8, 0.8, 0.2, 1
  61.        font_size: dp(14)
  62.        bold: True
  63.        on_press: root.show_info()
  64.  
  65. <InfoDialog>:
  66.    size_hint: (0.8, 0.5)
  67.    auto_dismiss: True
  68.    BoxLayout:
  69.        orientation: 'vertical'
  70.        padding: dp(20)
  71.        spacing: dp(10)
  72.        canvas.before:
  73.            Color:
  74.                rgba: 0.3, 0.3, 0.5, 1
  75.            Rectangle:
  76.                pos: self.pos
  77.                size: self.size
  78.        
  79.        Label:
  80.            text: root.title
  81.            font_size: dp(20)
  82.            bold: True
  83.            color: 1, 1, 1, 1
  84.            size_hint_y: 0.3
  85.        
  86.        Label:
  87.            text: root.description
  88.            font_size: dp(16)
  89.            color: 1, 1, 1, 1
  90.            text_size: self.width, None
  91.            valign: 'top'
  92.            halign: 'left'
  93.            size_hint_y: 0.7
  94.        
  95.        Button:
  96.            text: 'Close'
  97.            size_hint_y: 0.2
  98.            background_normal: ''
  99.            background_color: 0.8, 0.3, 0.3, 1
  100.            on_press: root.dismiss()
  101.  
  102. <SearchApplicationUI>:
  103.    orientation: 'vertical'
  104.    spacing: dp(5)
  105.    
  106.    # Results notification panel
  107.    BoxLayout:
  108.        id: notification_panel
  109.        size_hint_y: None
  110.        height: 0
  111.        opacity: 0
  112.        canvas.before:
  113.            Color:
  114.                rgba: 0.2, 0.8, 0.4, 0.9
  115.            Rectangle:
  116.                pos: self.pos
  117.                size: self.size
  118.        Label:
  119.            id: notification_label
  120.            text: ''
  121.            color: 1, 1, 1, 1
  122.            font_size: dp(18)
  123.            bold: True
  124.            halign: 'center'
  125.            padding: [dp(10), dp(5)]
  126.    
  127.    # Main content area with scrollable items
  128.    ScrollView:
  129.        id: content_scroll
  130.        size_hint_y: 1
  131.        do_scroll_y: True
  132.        
  133.        BoxLayout:
  134.            id: items_container
  135.            orientation: 'vertical'
  136.            size_hint_y: None
  137.            height: self.minimum_height
  138.            spacing: dp(5)
  139.            padding: [dp(10), dp(0)]
  140.    
  141.    # Search panel (fixed at the bottom)
  142.    BoxLayout:
  143.        id: search_controls
  144.        size_hint_y: None
  145.        height: dp(60)
  146.        padding: dp(10)
  147.        spacing: dp(5)
  148.        
  149.        TextInput:
  150.            id: search_field
  151.            hint_text: 'Enter search query...'
  152.            multiline: False
  153.            size_hint_x: 0.8
  154.            padding: [dp(10), (self.height - self.line_height)/2]
  155.            font_size: dp(16)
  156.            on_focus: root.on_search_focus_changed(*args)
  157.            on_text_validate: root.perform_search()
  158.        
  159.        Button:
  160.            id: action_btn
  161.            text: 'Add'
  162.            size_hint_x: 0.2
  163.            font_size: dp(13)
  164.            bold: True
  165.            background_normal: ''
  166.            background_color: (0.4, 0.6, 0.4, 1)
  167.            on_press: root.toggle_notification_panel()
  168.    
  169.    # Invisible overlay for keyboard dismissal
  170.    ClickableOverlay:
  171.        id: keyboard_dismiss_area
  172.        size_hint_y: None
  173.        height: 0
  174.        on_press: root.hide_virtual_keyboard()
  175. ''')
  176.  
  177.  
  178. class ClickableOverlay(ButtonBehavior, Widget):
  179.     """Transparent overlay for handling keyboard dismissal clicks"""
  180.     pass
  181.  
  182.  
  183. class InfoDialog(ModalView):
  184.     """Custom dialog for displaying item information"""
  185.     title = StringProperty('')
  186.     description = StringProperty('')
  187.  
  188.  
  189. class ContentItem(ButtonBehavior, BoxLayout):
  190.     """Interactive content item with title and information button"""
  191.     item_title = StringProperty('')
  192.     item_description = StringProperty('')
  193.    
  194.     def __init__(self, item_title="", item_description="", **kwargs):
  195.         super().__init__(**kwargs)
  196.         self.item_title = item_title
  197.         self.item_description = item_description
  198.    
  199.     def on_press(self):
  200.         app = App.get_running_app()
  201.         app.root.ids.notification_label.text = f"Selected: {self.item_title}"
  202.         if app.root.ids.notification_panel.height == 0:
  203.             app.root.show_notification_panel()
  204.    
  205.     def show_info(self):
  206.         """Display information dialog for this item"""
  207.         dialog = InfoDialog(title=self.item_title,
  208.                           description=self.item_description)
  209.         dialog.open()
  210.  
  211.  
  212. class SearchApplicationUI(BoxLayout):
  213.     """Main application interface with search functionality"""
  214.    
  215.     def __init__(self, **kwargs):
  216.         super().__init__(**kwargs)
  217.        
  218.         # 1. Инициализация переменной с высотой по умолчанию
  219.         self.keyboard_height = dp(0)  # Значение по умолчанию
  220.        
  221.         # 2. Запоминаем исходную высоту окна
  222.         self.original_window_height = Window.height
  223.        
  224.         # 3. Настройка внешнего вида
  225.         Window.clearcolor = (0.4, 0.4, 0.4, 1)
  226.        
  227.         # 4. Инициализация контента
  228.         self.initialize_content()
  229.        
  230.         # 5. Привязка обработчиков событий
  231.         Window.bind(on_keyboard=self.handle_keyboard_event)
  232.         Window.bind(on_resize=self.handle_window_resize)
  233.        
  234.         # 6. Запуск измерения клавиатуры с небольшой задержкой
  235.         Clock.schedule_once(lambda dt: self.measure_keyboard_height(), 1)
  236.  
  237.     def handle_window_resize(self, window, width, height):
  238.         """Обработчик изменения размера окна"""
  239.         # Здесь можно добавить логику реагирования на изменение размера окна
  240.         pass
  241.  
  242.     def measure_keyboard_height(self):
  243.         """Временный показ клавиатуры для определения её высоты"""
  244.         if not hasattr(self, '_measurement_done'):
  245.             # Устанавливаем фокус в текстовое поле, чтобы вызвать клавиатуру
  246.             self.ids.search_field.focus = True  # Исправлено с search_input на search_field
  247.            
  248.             # Запланировать замер через 0.5 секунды, когда клавиатура точно появится
  249.             Clock.schedule_once(self._finish_measurement, 0.5)
  250.    
  251.     def _finish_measurement(self, dt):
  252.         """Завершение процесса измерения высоты клавиатуры"""
  253.         # Сравниваем текущую высоту окна с исходной
  254.         if Window.height < self.original_window_height:
  255.             # Разница в высоте и есть высота клавиатуры
  256.             self.keyboard_height = self.original_window_height - Window.height
  257.             print(f"Keyboard height measured: {self.keyboard_height}dp")
  258.        
  259.         # Убираем фокус и скрываем клавиатуру
  260.         self.ids.search_field.focus = False
  261.         self._measurement_done = True
  262.    
  263.     def handle_keyboard_event(self, window, key, *args):
  264.         """Handle hardware back button press"""
  265.         if key == 27:  # ESC key
  266.             if self.ids.search_field.focus:
  267.                 self.hide_virtual_keyboard()
  268.                 return True
  269.             return False
  270.  
  271.     def hide_virtual_keyboard(self):
  272.         """Dismiss the virtual keyboard"""
  273.         self.ids.search_field.focus = False
  274.    
  275.     def initialize_content(self):
  276.         """Populate the content area with sample items"""
  277.         for i in range(1, 21):
  278.             item = ContentItem(
  279.                 item_title=f'Item {i}',
  280.                 item_description=f'Detailed description for item {i}. '
  281.                                f'This contains all relevant information about the item.'
  282.             )
  283.             self.ids.items_container.add_widget(item)
  284.    
  285.     def on_search_focus_changed(self, instance, has_focus):
  286.         """Handle search field focus changes"""
  287.         self.ids.keyboard_dismiss_area.height = self.keyboard_height if has_focus else 0
  288.    
  289.     def on_search_focus_changed(self, instance, has_focus):
  290.         """Handle search field focus changes"""
  291.         self.ids.keyboard_dismiss_area.height = self.keyboard_height if has_focus else 0
  292.    
  293.     def toggle_notification_panel(self):
  294.         """Toggle the notification panel visibility"""
  295.         if self.ids.notification_panel.height == 0:
  296.             query = self.ids.search_field.text.strip()
  297.             if query:
  298.                 self.ids.notification_label.text = f"Added: {query}"
  299.                 self.show_notification_panel()
  300.         else:
  301.             self.hide_notification_panel()
  302.    
  303.     def show_notification_panel(self):
  304.         """Animate notification panel appearance"""
  305.         Animation(height=dp(50), opacity=1, duration=0.3).start(self.ids.notification_panel)
  306.         self.ids.action_btn.text = "Remove"
  307.         self.ids.action_btn.background_color = (0.8, 0.3, 0.3, 1)
  308.    
  309.     def hide_notification_panel(self):
  310.         """Animate notification panel disappearance"""
  311.         Animation(height=0, opacity=0, duration=0.3).start(self.ids.notification_panel)
  312.         self.ids.action_btn.text = "Add"
  313.         self.ids.action_btn.background_color = (0.4, 0.6, 0.4, 1)
  314.    
  315.     def perform_search(self):
  316.         """Execute search operation"""
  317.         query = self.ids.search_field.text.strip()
  318.         if query:
  319.             self.ids.notification_label.text = f"Found: {query}"
  320.             if self.ids.notification_panel.height == 0:
  321.                 self.show_notification_panel()
  322.  
  323.  
  324. class SearchApplication(App):
  325.     """Main application class"""
  326.  
  327.     def build(self):
  328.         return SearchApplicationUI()
  329.  
  330.  
  331. if __name__ == '__main__':
  332.     SearchApplication().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement