Advertisement
soulseb

neploho

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