0

I have a general question about how to design dynamic UI elements in Android (with Java).

I would like to have a thermometer in my app that depending on some external information increases or decreases a red bar(shown below). enter image description here. How can i design something like this in Android?

I could for example just design the thermometer without the red bar as a jpeg with some drawing program and then somehow implement the red bar in Android as an object that can be changed programmatically whereas the 'rim' of the thermometer does not change. The problem I see with this approach is that I believe it is extremely difficult to match the rim of the thermometer with the red bar for different screen sizes and resolutions. Do you have another suggestion on how I could do something like this? Is there maybe a library for this?

I'd appreciate every comment as I have no experience whatsoever generally with designing such dynamic UI objects.

Narendra_Nath
  • 4,578
  • 3
  • 13
  • 31
VanessaF
  • 515
  • 11
  • 36

2 Answers2

2

Updated Answer:

I have created a demo project on Github here. This project has the Thermometer custom view in which the outer thermometer is drawn from an image file and the inside mercury view of the thermometer is drawn from the code. You can look over the project of user kofigyan I shared in my previous answer for other customizations.

Previous Answer:

I think what are you looking for is creating Custom Views in Android.

You can extend the Android View class and can create your Custom View. The View has a Canvas object on which you can draw the shape of a Thermo-meter and can build functionalities to change the state of your shape in your subclass itself. Moreover, with the Paint object, you can paint your drawn shape.

I found this project on Github by a user kofigyan.

Nikhil Jain
  • 649
  • 5
  • 11
  • 1
    This should be the accepted answer. The project from Github was really helpful. – Narendra_Nath Apr 15 '21 at 19:15
  • Thanks Nikhil for your answer. So I should not draw the outside rim of the thermometer (or any other object) by using a drawing programm? But with the drawing programm I have way more flexibility of designing objects and it is way better than and less complex than the Android drawing objects – VanessaF Apr 18 '21 at 07:01
  • @VanessaF You're welcome! I mean you need to draw the thermometer(or any other object) as per your design on the Canvas object of your Custom View. You can go through the GitHub link I shared in my answer that will help you to create your own custom view. – Nikhil Jain Apr 18 '21 at 07:11
  • Thanks Nikhil for your answer and effort. I really appreciate it. Basically it is not about the thermometer itself (this is why there is no need for me to use the github page) but generally about dynamic content. My question is whether I can just use a drawing programm for the outside rim (which is static) and then use the Canvas object for the dynamic part? – VanessaF Apr 18 '21 at 07:16
  • Yes, you can do it. – Nikhil Jain Apr 18 '21 at 07:19
  • Thanks for your further answer Nikhil. As mentioned in my question the problem I see with this approach is that I believe it is extremely difficult to match the rim of the thermometer with the red bar for different screen sizes and resolutions. Do you have any suggestion how I could combine the output of a drawing tool with a dynamic canvas element or is this not really possible in a good way? – VanessaF Apr 18 '21 at 07:21
  • Yes, it will be a little tricky to do this. So in this case, you will draw your image (created from a drawing program) in some ratio to the canvas width and height and you will draw the dynamic content on the Canvas in the ratio to the canvas width and height so that it will be placed properly according to your image content on Canvas. So even for different screen sizes, if the Canvas shrinks or scales then the whole drawing alignments don't get affected. – Nikhil Jain Apr 18 '21 at 07:35
  • Thanks Nikhil for your answer. How can I " will draw your image (created from a drawing program) in some ratio to the canvas " as you suggested? Would you adivice me to draw the thermometer in a drawing programm of directly in Android? Basically drawing in Android in quite complex and difficult, this is why I would prefer a drawing tool. But I see the problem that it is quite difficult to fit this to different sceen sizes with dynamic components – VanessaF Apr 22 '21 at 16:47
  • Also one question about the canvas. Do you draw the canvas in the XML layout file or how else can you position the canvas into the XML layout file – VanessaF Apr 22 '21 at 16:48
  • @VanessaF can you share your jpeg or png file from the drawing program? I will try to share some sample code. – Nikhil Jain Apr 23 '21 at 12:58
  • Thanks a lot Nikhil for your further answer and effort. I really appreciate it. Basically the thermometer that I posted is a jpeg file from a drawing program. I indeed want to use this thermometer. – VanessaF Apr 23 '21 at 16:20
  • @NikhilJain: Is the thermometer jpeg okay for what you wanted? – VanessaF Apr 25 '21 at 07:14
  • @VanessaF I used your thermometer image and I am currently working on a demo project to show how you can merge your image from the drawing program and canvas drawing, I will share it in my answer soon. – Nikhil Jain Apr 25 '21 at 17:27
  • 1
    @VanessaF I have updated my answer. Have a look at it and let me know for any issues. – Nikhil Jain Apr 28 '21 at 05:30
  • Thanks a lot Nikhil for your answer and effort. I really appreciate it. How did you approach the problem? I would have a hard time setting up such a code on my own as I do not really understand what you are doing (I have no experience with canvas or drawing in Android). So I can't ask any specific question as there would be too many. This is why I just would like to know how you can approch something like this. – VanessaF Apr 29 '21 at 17:03
  • Thanks for your answer and effort Nikhil. I really appreciate it. I upvoted and accepted your answer. Still, I would highly appreciate it, if you could comment my last comment and give me some advice as to how to approach such problems (because for me it looks quite complex and I would not know where to start and how to proceed) – VanessaF Apr 30 '21 at 16:34
  • Let's continue the discussion in chat - https://chat.stackoverflow.com/rooms/231842/room-for-nikhil-jain-and-vanessaf – Nikhil Jain May 02 '21 at 07:48
  • Hi Nikhil it's me again. Thanks for your answers. Could you maybe give me some advice how to approach such a problem because I had a look into your code and I have to admit that I do not understand it at all and it is quite complex for me (not only because there is also Kotlin code that I do not understand at all because I have no experience whatsoever with Kotlin. But I also do not understand the Java code because of the used packages). What would you do first when you want to design dynamic UI components and how would you proceed? I'd highly appreciate every further comment. – VanessaF May 12 '21 at 15:46
  • @NikhilJain: Any comments to my last comment? I'd highly appreciate every further comment from you as I have problems understanding your code and your approach. – VanessaF May 13 '21 at 15:52
  • @VanessaF sorry I was away these few days. I am not sure if you have experience with Android Canvas API and drawing bitmap on Canvas. Let me know what are the things that you didn't understand from the code and did you go through this link https://developer.android.com/guide/topics/ui/custom-components? I will try to help you to walk through my shared code example. – Nikhil Jain May 13 '21 at 16:32
  • Thanks Nikhil for your comment. Basically as stated before, I have no experience with Canvas or drawing bitmaps in any programming language. This is why your code is quite complex for me and I many questions. I am not sure whether this is really the best way to learning how to create dynamic UI elements because I have way to many questions that you can't answer all. I read the link you posted but it does not help that much as I do not understand most of the topics covered there. Nonetheless I will as my most urgent questions at the moment about the thermometer class of your code. – VanessaF May 14 '21 at 14:54
  • 1) Why do you use 3 different constructors for the thermometer and what are they doing? 2) I do not understand at all what you are doing in the onSizeChanged method and where do you get the calcualtion equations from? How can you derive these equations? For me this is just completely incomprehendible. Sometime you multiply by 0.98, sometimes you divide by 2, sometimes by 4.6f etc. Bascially I do not understand every single line there. 3) Why do we need the onMeasureMethod and what is done there? I read about it in the documentation but do not understand why we have to measure anything and how? – VanessaF May 14 '21 at 14:58
  • 4) on the drawThermometer method why do you use `canvas.drawBitmap(bitmap, left, top, new Paint());` What are the parameters left and top used for and how did you derive their values? 5) Is it also possible instead of using a jpeg file to use a vector graphic file (svg) that scales automatically? 6) As far as I see it the methods `setThermometerColor`, `onMeasure` and `onSizeChanged` are never called? Did you do this on purpose? – VanessaF May 14 '21 at 15:05
  • 1) Although, all three constructors are not required. You can go through this answer -https://stackoverflow.com/questions/9195713/do-i-need-all-three-constructors-for-an-android-custom-view . Note: I didn't call the init method in the first two constructors so I will update the code. – Nikhil Jain May 15 '21 at 16:59
  • 2) First I am calculating the bitmap width and height based on the ratio (this bitmap is our image -https://github.com/nikhiljainlive/CanvasDrawingAndBitmap/blob/main/app/src/main/res/drawable/thermometer_container.png ) so the width or height is 98% (i.e. multiplied by 0.98) of the root view width or height. Actually, in order to get the proper values for maintaining the view responsiveness, I have done a bit of hit and trial to get appropriate values. So, I will suggest you try changing the values and see the results; I think that will help you to understand the calculations. – Nikhil Jain May 15 '21 at 17:24
  • 2) Continued - But what you can see from my code, I am calculating these positions and values by taking the proportions on the root view's width and height and the bitmap image's width and height. – Nikhil Jain May 15 '21 at 17:26
  • 3) In onMeasure method of our Thermometer view class, we are going to tell the parent of this view that how much width and height should take while being drawn. For more information, have a look at this article - https://medium.com/@quiro91/custom-view-mastering-onmeasure-a0a0bb11784d – Nikhil Jain May 15 '21 at 17:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232461/discussion-between-nikhil-jain-and-vanessaf). – Nikhil Jain May 15 '21 at 17:32
  • @NikhilJain: Thanks Nikhil for the answers in the chat. There are still some questions regarding your code that you can see in the chat. Would you mind having a look at them? – VanessaF Jun 09 '21 at 15:58
  • Hi @VanessaF, Sorry for keeping you waiting as I was a bit occupied with other work. I have answered your questions in the chat, please have a look at them and let me know for any issues. – Nikhil Jain Jun 13 '21 at 20:23
  • Thanks Nikhil for your answers and tremendous effort. I have read your answers in the chat and I have follow up questions to them (see in the chat). If you have time and if your are willing to I'd highly appreciate it if you could answer them. – VanessaF Jun 18 '21 at 16:05
  • @NikhilJain: Thanks for your answers. Any comments to my follow-up questions in the chat? – VanessaF Jun 22 '21 at 20:13
  • @NikhilJain: Thanks for your answers and effort. I really appreciate it. I have some follow up questions to your anwers regarding your suggested code. You can see them in the chat. I'd be quite happy if you could have a look at them. – VanessaF Jun 27 '21 at 07:19
  • @NikhilJain: Do you not have any time any more to have a look at my comment in the chat? As I have some problems understanding your suggested code I would highly appreciate it if you could answer my follow-up questions. But if you do not have time any more I could also understand that. – VanessaF Jun 30 '21 at 17:47
  • 1
    @VanessaF Please look through my previous chat messages and also new chat messages. – Nikhil Jain Jul 01 '21 at 19:01
  • @NikhilJain: Thanks a lot for your answers and tremendous effort. I have new (and old) questions to what you wrote about your suggested code in the chat. I f you have time and if you are willing to, you can have a look at them. – VanessaF Jul 07 '21 at 17:10
  • @NikhilJain: Thanks NikhilJain for your answers. I posted some follow up question a while ago in the chat about reusing your suggested code and how to adjust the size of it. Would you mind having a look at it? I'd highly appreciate every further comment from you. – VanessaF Aug 01 '21 at 15:11
  • @NikhilJain: Any further comments in the chat? – VanessaF Aug 04 '21 at 15:50
  • @NikhilJain: Why are you not responding anymore? I'd highly appreciate any further comment from you. – VanessaF Aug 17 '21 at 18:44
  • @NikhilJain: Any comments to my last comments in the chat? Would be quite cool if you could have a look at them – VanessaF Aug 30 '21 at 18:04
  • @VanessaF I had answered your questions and if my project doesn't satisfy your use case, you can check my previous answer section on the same answer and you can use that solution. – Nikhil Jain Sep 05 '21 at 14:32
  • 1
    Thanks a lot for your tremendous effort Nikhil. I can fully understand that you can't help me any more as you have already spent quite much time on it. Unfortunately I can't use your suggested code as it creates a lot of problems and I have very big difficulties understand it. And the link you gave in the answer does not help at all as this thermometer is not suitable for my case. Nevertheless I really appreciate your tremendous effort. I will try to look for another solution to my problem. – VanessaF Sep 06 '21 at 18:19
  • @NikhilJain: I awarded a bounty of 50 points to you due to your great effort. – VanessaF Sep 08 '21 at 15:18
  • @VanessaF Thanks! I really appreciate it. – Nikhil Jain Sep 09 '21 at 18:54
1

For having a dynamic ui you can take two approaches.

  1. Jetpack Compose(not being discussed since it's still in Beta)
  2. LiveData and observer pattern

In LiveData and observer pattern. Give the temperature as a LiveData variable(in your ViewModel) and implement an Observer in your MainActivity which gets triggered automatically when the value of the temperature live data changes.

For getting the output graphic you can use a canvas and then draw on it and tie it to the temperature variable. You could for example use the Canvas.drawRect function to create a short or long rectangle depending on the temperature. ( the part from the circle to the top of the thermometer can be the rectangle)

Narendra_Nath
  • 4,578
  • 3
  • 13
  • 31
  • Thanks Narendra for your answer. But I can also do this without live data, right? I could for example just implement a thread that observers one variable all the time and based on this it changes the shape of the graphic. I am not a big fan of live data. I once had a look at it and it seems quite (unecessarily) complex – VanessaF Apr 18 '21 at 07:03
  • Yes absolutely. You just need a variable you will be monitoring continuously .. How you do it is your discretion – Narendra_Nath Apr 18 '21 at 07:16