Перейти к содержанию
Fire Monkey от А до Я

ENERGY

Пользователи
  • Постов

    568
  • Зарегистрирован

  • Посещение

  • Победитель дней

    57

Сообщения, опубликованные ENERGY

  1. Нужно закрывать обычный Messagebox если юзер ничего не нажимает через какой то интервал времени.

    Как его закрыть? Может можно тапнуть программно? Или тапнуть куда то по форме (если тапнуть вне messagebox он тоже закрывается). Только вот как это сделать. В Windows я бы отправлял сообщения или эмулировал нажатие enter на клавиатуре при помощи keyboard_event, а вот что делать на Android?

  2. Цитата

    подпись слева (в левой колонке TLabel) и в правой колонке компоненты редактирования (TEdit, TComboBox и другие).

    В мобильных приложениях надо экономить место. Поэтому лэйбл положите прямо внутрь Tedit и TCombobox или Memo (можно сделать в инспекторе объектов), поставьте ему enabled := false чтобы он был серого цвета. Затем на OnChange или OnChangeTracking проверяйте кол. символов и прячьте лэйбл: 

    Label1.Visible :=   Edit1.Text.Length = 0;

  3. Цитата

    Но, как я понял, мои ответы отправляются в пустоту без попыток осмысления

    Я все внимательно читаю, просто думал вы про Design Time говорите.

    Исправил на вариант без тэга.

    Но имя все равно используется чтобы идентифицировать слой, но уже стало гораздо легче :)

     vDest := Self.Destination.Add;
      vLayer := vDest.Layers.Add;
      vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width,
          vSource.MultiResBitmap.Height);
      vLayer.Name := vSource.Name;
      Result := vDest.Index;

  4. @RoschinSpb

    Цитата

    Еще раз обращаю внимание: обязательный идентификатор инициализируется значением по умолчанию.   по сути он и является опциональным.

    По сути он как раз является обязательным, потому что при добавлении картинки в список в runtime, нужно указывать уникальное имя, притом в двух местах. Было бы классно, если бы компонент сам создавал это имя (в Runtime), конечно было бы удобней если имя было представлено как необязательное поле Description.

    Цитата

    Использование Tag мало того, что просто дурной тон, оно еще и лишнее и снижает базовую функциональность.

    Ну без Tag пришлось бы вводит переменную-счетчик в класс текущей формы, что имхо только усложняет. А если форм несколько?
    Использовать глобальную переменную, тоже вариант, но это же костыль, такой же как и тэг. А если используются костыли, в таком простой случае, значит что-то не так..

    Цитата

    И вообще мне странно, что Вы сначала жалуетесь, на излишнюю сложность и уже на следующей строке перекладываете на программиста куда более сложную задачу (формировать отдельные списки/структуры).

    Это имя нужно только компоненту TImageList. А юзеру чтобы отличать картинки в DesignTime в ImageList достаточно посмотреть на картинку. В остальных случаях - обращение через индексы.

    Туда не запишешь какое то серьезное описание. Как вы представляете это? Одни значения для обрабатываемой картинки (размер, имя, разрешение, и многое др.) храним и читаем со специально созданного для этого класса, а описание\имя читаем с ImageList?

    Это же не удобно и запутает. Плюс ImageList находится в юните GUI, где только GUI код,

    а вся логика работы обычно в отдельном классе ядра и к тому же код может быть мультипоточный.

    Плюс обычно если программисту нужно хранить описание картинки или имя, то оно должны быть writeable. А в ImageList  оно readonly.

    Имхо это велосипед, явно усложняющий работу.

    Цитата

     а при чем здесь StringList, здесь больше уместна аналогия с TComponent.Name.

    Какая разница какой тип данных содержит список - строки, картинки - это просто data куски лежащие в памяти. 

    Цитата

    Если же речь идет о динамической загрузке, это почти всегда что-то нестандартное, тут уже возможны всякие варианты

    Есть определенные стандарты написания похожих компонентов, втч. это и имена методов (Add, Remove, Insert etc),  имхо разработчикам следовало бы держаться стандартов Delphi для списков, к которым за годы все привыкли.

  5. Цитата

    Вы бы смогли догадаться, что изображено на этих картинках без доп. описания? Картинки конечно неважные, но в коде-то Вы их вообще не видите.

    Имена можно было ввести, но опционально (description) - нужно юзеру, - добавил.  Не нужно ну и не надо.

    В большинстве случаев описание не нужно. А те кому это нужно, обычно хранят это в своих структурах, в отдельном списке, где можно кроме описания, сохранить и др. параметры (путь к файлу, адрес итд).

    А сейчас это обязательный идентификатор, который, имхо, усложняет работу со списком..

     

    Цитата

    Допустим в приложении появилась вторая, третья, N+1 форма. Я не знаю отнаследовалась она, или просто скопипастилась, или Вы что-то добавили в Design-Time, так или иначе есть ненулевая вероятность получить неоднократное добавление одного и того же

    Ну и что, это задача уже ложиться на программиста, причем здесь ImageList.

    Можно и не замещать, а просто добавить новую картинку, с тем же именем или игнорировать добавление. Как например в StringList сделано. Там по умолчанию выключено определение дубликатов и добавляется новая строка.. Представьте если бы StringList по умолчанию возбуждал исключение на дубликат строки, весело было бы..

  6. @RoschinSpb

    Цитата

    Использование Tag, как бы намекает ;) Не стоит скрывать свойство TCustomSourceItem.Name от пользователя, пусть сам заботится об уникальности (не такая уж это большая проблема).

    Я честно говоря вообще не понимаю зачем туда ввели строковые имена и зачем они пользователю сдались. Индексов хватило бы с головой и быстрее бы работало - не нужно перебирать компаратором все эти массивы строк, и меньше бы памяти брало.

     

    Цитата

    Это свойство может быть использовано для предотвращения случайной повторной загрузки, допустим если есть картинка с указанным названием поднимать исключение. 

    И это я тоже не понимаю, зачем нужно делать исключение на этот случай, по идее нужно было молча заменить картинку.

     

    У Delphi есть широкий выбор разнообразных списков, очередей, cтэков, массивов, деревьев и никогда в них не использовались имена. Для идентификации и унификации всегда использовалось число-индекс. У этого подхода гораздо больше плюсов, чем у строковых идентификаторов, почему решили отойти от этого стандарта, не понимаю...

  7. type
      TImageListHelper = class helper for TImageList
        function Add(aBitmap: TBitmap): integer;
      end;
    
    function TImageListHelper.Add(aBitmap: TBitmap): integer;
    const
      SCALE = 1;
    var
      vSource: TCustomSourceItem;
      vBitmapItem: TCustomBitmapItem;
      vDest: TCustomDestinationItem;
      vLayer: TLayer;
    begin
      Result := -1;
      if (aBitmap.Width = 0) or (aBitmap.Height = 0) then exit;
    
      // add source bitmap
      vSource := Source.Add;
      vSource.MultiResBitmap.TransparentColor := TColorRec.Fuchsia;
      vSource.MultiResBitmap.SizeKind := TSizeKind.Source;
      vSource.MultiResBitmap.Width := Round(aBitmap.Width / SCALE);
      vSource.MultiResBitmap.Height := Round(aBitmap.Height / SCALE);
      vBitmapItem := vSource.MultiResBitmap.ItemByScale(SCALE, True, True);
      if vBitmapItem = nil then
      begin
        vBitmapItem := vSource.MultiResBitmap.Add;
        vBitmapItem.Scale := Scale;
      end;
      vBitmapItem.Bitmap.Assign(aBitmap);
    
      vDest := Destination.Add;
      vLayer := vDest.Layers.Add;
      vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width,
          vSource.MultiResBitmap.Height);
      vLayer.Name := vSource.Name;
      Result := vDest.Index;
    end;

     

    Хелпер  позволяет добавлять свои методы, не наследуясь от класса.

    После этого можно обращаться к любому ImageList 

    ImageList1.Add(MyBitmap);

     

  8. Не нашел я к сожалению в этой и других ветках простой код для добавления TBitmap в ImageList без лишних элементов. Все приходиться делать самому: 

    Helper для ImageList

    type
      TImageListHelper = class helper for TImageList
        function Add(aBitmap: TBitmap): integer;
      end;
    
    function TImageListHelper.Add(aBitmap: TBitmap): integer;
    const
      SCALE = 1;
    var
      vSource: TCustomSourceItem;
      vBitmapItem: TCustomBitmapItem;
      vDest: TCustomDestinationItem;
      vLayer: TLayer;
    begin
      Result := -1;
      if (aBitmap.Width = 0) or (aBitmap.Height = 0) then exit;
    
      // add source bitmap
      vSource := Source.Add;
      vSource.MultiResBitmap.TransparentColor := TColorRec.Fuchsia;
      vSource.MultiResBitmap.SizeKind := TSizeKind.Source;
      vSource.MultiResBitmap.Width := Round(aBitmap.Width / SCALE);
      vSource.MultiResBitmap.Height := Round(aBitmap.Height / SCALE);
      vBitmapItem := vSource.MultiResBitmap.ItemByScale(SCALE, True, True);
      if vBitmapItem = nil then
      begin
        vBitmapItem := vSource.MultiResBitmap.Add;
        vBitmapItem.Scale := Scale;
      end;
      vBitmapItem.Bitmap.Assign(aBitmap);
    
      vDest := Destination.Add;
      vLayer := vDest.Layers.Add;
      vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width,
          vSource.MultiResBitmap.Height);
      vLayer.Name := vSource.Name;
      Result := vDest.Index;
    end;

     

    Хелпер  позволяет добавлять свои методы, не наследуясь от класса.

    После этого можно обращаться к любому ImageList 

    ImageList1.Add(MyBitmap);

     

  9.  

    Евгений Корепов

    https://forums.embarcadero.com/thread.jspa?threadID=248231&tstart=0

    https://forums.embarcadero.com/thread.jspa?threadID=248237&tstart=0

    https://quality.embarcadero.com/browse/RSP-17162

    Плюс там 

    1. Application lost all effects...glow effects on buttons etc.
    2. TAniIndicator for example does work anymore. 
    3. Simple TEdit is very slow in response.
    4. TListBoxes are very slow. Enabling and disabling TListBoxItems takes seconds to complete, leaving the application useless. 
    5. The memory consumption seems higher than the Berlin compiled version.
    6. FormShow and FormActivate is called when the Android splash is still showing. I still have no idea when the for is actually showing!
    7. Tab transistions is not happening at all.
    8. Application crashed after a while of waiting for some TListboxItems to appear. (10 of them)

     

    Марко в своем блоге подтвердил: "issues with animation on Android are being investigated. Probably related with the changes in threading model".

  10. На всех Android версиях от 4.0.4 до 7. На процессорах ARMv7. Также работает на Intel (Atom) процессорах через эмулятор ARM который разрабатывает Intel - libhoudini  обычно уже сразу установлен в таких девайсах.

    Также работает на процессорах  ARMv8 (x64) т.к. они поддерживают  инструкции ARMv7.

    По факту это наибольший сегмент мобильных устройств. Втч это Android Wear, Google Glass, разные Smart TV, Amazon FireTV, Amazon FirePhone, BlackBerry, см. статью.

    Не работает на ARMv6 и ниже довольный старый сегмент девайсов, ~2010, там и Android второй версии. Aндроид меньше 4 используют около ~1% девайсов сейчас (статистика).

     

    http://docwiki.embarcadero.com/PlatformStatus/en/Main_Page

    http://docwiki.embarcadero.com/RADStudio/Berlin/en/Android_Devices_Supported_for_Application_Development

    Интересная статья: 

    https://community.embarcadero.com/blogs?view=entry&id=8520

  11. Проблема в стиле. Если его удалить, или загрузить другой то все работает.

    Загрузите любой стиль например c:\Users\Public\Documents\Embarcadero\Studio\18.0\Styles\Win10Modern.Style и используйте его или если нужен свой, то посмотрите как там делается menuitemstyle.

    Там TLayout - со Stylename = glyph  и на нем лежит TGlyph с Stylename - glyphstyle.

     

  12. Если кто то хочет проэмулировать данную проблему, используйте эмулятор Nox. Он основан на Intel архитектуре и именно поэтому самый быстрый среди всех эмуляторов. Delphi программы на нем работают. И там та же проблема с заголовком.

    Автор переименуйте пожалуйста тему на Смещается заголовок на Android Intel или что то похожее

  13. Большое спасибо за помощь, добрый человек!

    Еще добавлю, чтобы сменить фон Item'a (например на прозрачный)  или добавить какие то рюшечки (например полоски между пунктами), на вышеуказанном примере: нужно зайти в стили, и редактировать imagesui.png файл который находится внутри контейнера listviewstyle_panel (не снаружи, т.к. там есть точно такой же). Т.е. жмем на imagesui.png > MultiresBitmap > выбираем нужный, и слева в инспекторе объектов жмем свойство Bitmap с помощью которого этот файл можно сохранить,(а потом и загрузить) на диск.

  14. Огромное вам спасибо. Разобрался за несколько минут.

    Вопрос: 

    1. Что делать, если нужно загружать туда фотографии с диска, они большого размера, грузить их в TimageList займет много ресурсов - туда разве что можно загрузить превью фотографии, да и превью хотелось бы загружать по потребности.

    Насколько я понимаю в FMX TLIstView нету режима виртуального списка, когда нужно отрисовывать только видимые Items как было в VCL? Я поискал, вроде стандартного механизма нет.

    Есть идея отнаследоваться от TImageList и сделать чтобы он подгружал нужные фотки, по мере запроса... Будет этакий кэширующий виртуальный TImageList .

    2. Вы не задумывались  создать в QC предложение с улучшенным TListView? Возможно добавят? Ведь вас уже рекламируют http://www.fmxexpress.com/very-customizable-listview-control-for-firemonkey-in-delphi-10-berlin-on-android-and-ios/

    2. Кстати много вылезает предупреждений и подсказок от компилятора, тут два варианта или забить их директивами в самом модуле ListView 

    {$WARN OFF}

    Или откомпилировать в dcu.

    [dcc32 Warning] FMX.ListView.pas(866): W1045 Property declaration references ancestor private 'TListViewBase.FSeparatorLeftOffset'
    [dcc32 Warning] FMX.ListView.pas(868): W1045 Property declaration references ancestor private 'TListViewBase.FSeparatorRightOffset'
    [dcc32 Warning] FMX.ListView.pas(871): W1045 Property declaration references ancestor private 'TListViewBase.FHorizontal'
    [dcc32 Warning] FMX.ListView.pas(872): W1045 Property declaration references ancestor private 'TListViewBase.FMakeSelectedItemVisible'
    [dcc32 Warning] FMX.ListView.pas(872): W1045 Property declaration references ancestor private 'TListViewBase.FMakeSelectedItemVisible'
    [dcc32 Warning] FMX.ListView.pas(874): W1045 Property declaration references ancestor private 'TListViewBase.FTopOffset'
    [dcc32 Warning] FMX.ListView.pas(875): W1045 Property declaration references ancestor private 'TListViewBase.FBottomOffset'
    [dcc32 Warning] FMX.ListView.pas(876): W1045 Property declaration references ancestor private 'TListViewBase.FAutoColumns'
    [dcc32 Warning] FMX.ListView.pas(877): W1045 Property declaration references ancestor private 'TListViewBase.FColumns'
    [dcc32 Warning] FMX.ListView.pas(878): W1045 Property declaration references ancestor private 'TListViewBase.FMarg'
    [dcc32 Warning] FMX.ListView.pas(879): W1045 Property declaration references ancestor private 'TListViewBase.FColumnWidth'
    [dcc32 Warning] FMX.ListView.pas(882): W1045 Property declaration references ancestor private 'TListViewBase.FShowScrollBar'

     

  15. Подскажите пожалуйста как реализовать такую вещь. Горизонтальный TListView где каждый Item это картинка, рястянутая целиком на Item.

    Я попробовал использовать компонент Равиля, за что ему больше спасибо!

    Никак не пойму (относительно недавно пришел с VCL) как нарисовать картинку целиком на Item на этом горизонтальном Item.

    Это через стили надо делать? У ListView же какие то специальные стили, они отличаются например от стилей ListBox. Жаль там нет ItemOwnerDraw как в VCL. Пытался разобрать код в AutoColumns в проекте Равиля, но не разобрался, там рисуется колонками и список совсем другого типа..

    Также еще один ньюанс не знаю даже как подойди к нему, между Items нужно сделать полоску конкретного цвета. Это в стилях по идее, левый и правый края Item закрасить надо?

    Спасибо, очень надеюсь. Нигде нет нормальной инфы по горизонтальным спискам..

  16. 5 часов назад, Равиль Зарипов (ZuBy) сказал:

    Не будем разбирать конкретно этот случай, пока Токио очень сырой.

    Сломали всё что можно было. (обсуждали в чате)

    Чтобы не плодить темы на форуме, вернитесь на Берлин апдейт 2, до какого нить хот-фикса от Ембы.

    Что ж вы такое интересное в чате обсуждаете, это же тема не на один час, и даже не на месяц. Могли бы и тему создать. Наверное потому что бот Ярослава постит и закрывает темы, так можно было в той же теме (Whats New in Tokyo) по обсуждать. @brovin-yaroslav это вам на заметку, большая просьба не закрывать темы-новости.

  17. Сделал решение для описанного выше варианта.

    Добавил его на Stackoverflow

     

    unit Misc.Android;
    
    interface
    
    uses
      SysUtils,
      Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers, Androidapi.JNI.JavaTypes,
      Androidapi.JNIBridge, Androidapi.JNI.Provider;
    
    type
      TGallery = class
      public
        class function GetLastImageID: integer;
        class function GetNextImageIDFromID(aFromID: integer; out aImagePath: string): integer;
        class function DeleteImageByID(aID: integer): boolean;
      end;
    
    
    implementation
    
    const
      _ID = '_id'; //  TJBaseColumns.JavaClass._ID   // uri in Androidapi.JNI.Provider
    
    { TGallery }
    
    {If you're using action TakePhotoFromCameraAction remember to set NeedSaveToAlbum to true.
     It does not work, because of Android problems, but it can work in future.}
    
    class function TGallery.GetLastImageID: integer;
    var
      vContent: JContentResolver;
      vValues: TJavaObjectArray<JString>;
      vOrderBy: JString;
      vCursor: JCursor;
    begin
      Result := -1;
      vContent := TAndroidHelper.Activity.getContentResolver;
    
      vValues := TJavaObjectArray<JString>.Create(1);
      vValues[0] := TJBaseColumns.JavaClass._ID;
    
      vOrderBy := StringToJString(_ID + ' DESC');
    
      vCursor := vContent.query(TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI,
          vValues, nil, nil, vOrderBy);
      try
        if vCursor.moveToFirst then
          Result := vCursor.getInt( vCursor.getColumnIndex(TJBaseColumns.JavaClass._ID) );
      finally
        vCursor.close;
      end
    end;
    
    // Result is next Image ID and its aImagePath - is path to jpg image
    class function TGallery.GetNextImageIDFromID(aFromID: integer; out aImagePath: string): integer;
    var
      vContent: JContentResolver;
      vValues: TJavaObjectArray<JString>;
      vFilter: JString;
      vOrderBy: JString;
      vArgs : TJavaObjectArray<JString>;
      vCursor: JCursor;
    begin
      Result := -1;
      aImagePath := '';
      vContent := TAndroidHelper.Activity.getContentResolver;
      vValues := TJavaObjectArray<JString>.Create(2);
      vValues[0] := TJMediaStore_MediaColumns.JavaClass.DATA;
      vValues[1] := TJBaseColumns.JavaClass._ID;
       // vValues[1] := TJMediaStore_MediaColumns.JavaClass.SIZE;
       // vValues[1] := TJImages_ImageColumns.JavaClass.DATE_TAKEN;
    
      vOrderBy := StringToJString(_ID + ' DESC');
      vFilter := StringToJString(_ID + '>?');
      vArgs := TJavaObjectArray<JString>.Create(1);  
      vArgs[0] := StringToJString(aFromID.ToString);
    
      vCursor := vContent.query(TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI,
         vValues, vFilter, vArgs, vOrderBy);
      try
        if (vCursor.getCount > 0) and vCursor.moveToFirst then
        begin
          Result := vCursor.getInt( vCursor.getColumnIndex(TJBaseColumns.JavaClass._ID) );
          // vCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN));
          //vSize := wCursor.getLong(wCursor.getColumnIndex(TJMediaStore_MediaColumns.JavaClass.SIZE));
          aImagePath := JStringToString(vCursor.getString(
              vCursor.getColumnIndex(TJMediaStore_MediaColumns.JavaClass.DATA) ));
        end;
      finally
        vCursor.close;
      end;
    end;
    
    class function TGallery.DeleteImageByID(aID: integer): boolean;
    var
      vContent: JContentResolver;
    begin
      vContent := TAndroidHelper.Activity.getContentResolver;
      Result := vContent.delete(TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI,
            StringToJString(_ID + '=' + aID.ToString), nil) = 1;
    end;
    
    end.
  18. Спасибо большое. Но странно почему сам компонент не умеет это делать стандартными гестурами, с двумя пальцами.

    Надо будет когда побольше времени появится, реализовать это.

    Также есть еще пример как делать зум двумя пальцами в 

    \Samples\Object Pascal\Mobile Snippets\InteractiveGestures\ImageZoom\

    Но там просто меняется высота и ширина компонента.

×
×
  • Создать...