Build a Clickable Calendar in Jetpack Compose with Canvas and Animations - Android Studio Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys and welcome to another video about jackpot compose and canvas in this video we are going to build such an interactive calendar where we can click on different days and we will see the corresponding list we have to do on this day in my case I've just added always the same you can see that the day is just changing and if you have a closer look then you can see we have also a cool animation here which starts at the point where we click and then it expands until it reaches the specific stay border like you can see here all right okay I'm in an empty jetpack on post project I have just removed the default created stuff from Android studio and also I've added some colors but I think we only need this three colors you can find them in my github's repository which is linked down below or simply use your own ones okay let's straight down with the calendar composer build for that we will have a private cons well a calendar rows which is equal to 5 and we will also have the cons 12 for the calendar columns which is equal to 7 you can also choose different values we will make the calendar looking depending on this calendar rows and calendar columns and then you can decide if you want to show like seven columns and five rows or some different rows and columns count then we will have a composable function which will be our calendar it takes the modifier which will be the default modifier here then we have a calendar inputs of type list of type calendar inputs and we first need to create this calendar input so we can go down here and create a data class normally I would put this in some kind of states or data folder package but for this tutorial this is fine this calendar inputs will have a value day of type ins and the value to those of type list of type string and we can set this to an empty list by default up here in our calendar composable we can then also Define an on date click Lambda function which provides an integer later so this will indicate on which day we actually clicked and will return nothing then we also have a stroke with so the the width of the different calendar bars we will set this to 15f by default if you want to make this calendar a little bit more smaller regarding these different lines then you can also adjust this value and we will also Pass a month here so that you can reuse this calendar for different months in this case in this tutorial we will just use September but you can also Implement some kind of logic with left and right errors to switch between different one and then you can pass the current month which you want to show down here in this calendar composable we can then Define a column and this column will have a text and the text will be our month the font rate for the month will be semi Bolt the color will be white and also the font size will be set to 40 SP and for the column as modifier we will pass the past modifier vulnerable and the vertical Arrangement will be Arrangement dot Space by NDP below our text we can then invoke our canvas the modifier will be modifier.filmex size so the canvas will expand to the whole width and it will be as high as this modifier here is minus the height of this text composable then we can open the draw scope and first we need the canvas height for calculations later the size dot height will give us that canvas height then we will have the canvas list which we will get from size dots with and we also can Define um X steps and Y steps so the different steps between the different days because they are depending on the canvas height and our calendar rows and the canvas within our calendar columns we can say well y steps is equal to Canvas Heights divided by our calendar rows then by well X steps is equal to Canvas width divided by the calendar columns after that we can draw a big rounded rect which is around our calendar grid so draw round rects for the color we will pass orange for the corner radius we will pass the corner radius with 25 F and 25 f for X and Y and for the style we will pass a stroke and The Strokes width will be our stroke width which we will get from this here when I work with canvas I always like to start the app as soon as possible so that we can always see what's currently drawn on the screen and we will also do this here so let's go up to our main activity and I will copy and paste the function here which creates our calendar items I don't think I should type this off here and I also think we should make this a little bit smaller here like this yeah I think you can still read this very well and what this function does is it just creates a calendar List It hovers over um 31 items here and for each item we will create this calendar input as I already showed in the introduction we will always have the same to-do's and just the day here changes and down here it returns our calendar input list then we can go up to our set content here we will have a box which takes the modifier this modifier will fill the max size and will set the background to gray the Box content alignment will be alignment dot top Center then we can open the box scope and in here we will invoke our calendar so like this let's put this in separate lines for the calendar input we will create a state well so well calendar input list by remember mutable State off creates calendar list so this is our private functioner which is down here this will create our calendar list then we can pass this here calendar input list we will leave the click logic empty for now because we will first draw the calendar and after that we will go for click events and for the month I will simply pass September here and of course if you would like to make this a year calendar where the user can switch between different months then you would need to apply some different state and data logic here but this tutorial will mainly focus on drawing the calendar and detecting the clicks on the different days and yeah but with some little adjustments you can also make this a real calendar which is also clickable regarding switching different months and all that stuff for the modifier we will pass the modifier dot padding 10dp and fill mix with the aspect ratio will be 1.3 F so the Calendar's width is 30 percent bigger than it's actually hired then we can start this and have a look at our rounded rect and I think this looks good so far now let's draw our grid for that we can use for Loops the first for Loop will be from 1 until our calendar Rose so this will be the lines from the left to the right and we only need four lines here because we have five rows so we will exclude calendar rows here which is 5 and start from one then we will say draw a line the color will be orange the start offset where the draw line should actually start will be offset 0f and our y steps multiplied with iron so we will start drawing at X is equal to 0 which is the left side of the canvas and our y steps which indicates the difference depths from the top to the bottom multiplied with I and if I is 1 then we will draw the first line for example and when if I is 2 then we will draw the second line but this is just the start offset we also need an end offset which will be offset and you can pause this video and think about which is our X offset here it's the canvas width because we draw from the left to the right and the very right is the canvas width and of course we also have device steps multiplied with I here and then we have also a stroke width which will be our stroke wave which we will get past from above then we can start this and you will see what's this does here you can see now these are the horizontal lines here we can copy and paste this for Loop here for our calendar rows and do some little adjustments we will say um 10 in the columns here the column will be still orange and now we need to change a little bit here here we need our x steps multiplied with I as well and for the columns we will always start at the top so the Y value will be 0f and then we can here say x steps minus I as well because our x value does not change from the start to the end because we draw from the top to the bottom and for the Y value you can pause again now and it should be clear I think the canvas height of course and the rest Remains the Same then we can start this again and now you can see we have a nice grid here we could also make this a nested for Loop and only draw in here inside the inner loop and we could draw rectangles here for each day one rectangle but I think these two for Loops which run after each other is a little bit more easy to understand and also if we would use direct angle approach then they would be always overthrow some sections of rectangles which are around this rectangle now we will draw the different day numbers which are in each rectangle here in our grids at the top left for that we first need the text Heights which is equal to 17 dp.2 pixel this is just a value I experimented with you can also use another text size but we need this text High here for applying it off that that they don't get drawn over their grids actually now we will enter a for loop again for I in calendar input dot Indie sales so we go over each item here in this calendar input and they are also our days so for each day we will enter this for Loop in here we need the text positioner X which is equal to X steps multiplied with I modulo Highlander columns plus our stroke width I will explain this after we Define the text position y as well so text position Y is equal to I divided by our calendar column multiplied with Y steps plus the text height plus the stroke width divided by 2. okay what does this mean we have our text position X which is the position of the text drawing on the x-axis the horizontal axis then we have the text position Y which is the vertical axis so from the top to the bottom then for the text position X for example we have the X steps so each step for each day so from the left one step to the right and to the right and so on and we multiply this with I modulo our calendar columns I hope you know what this modulo does if not you obviously need to check this out and I will go from 0 to 30 for example if we have 31 days and this modulo always returns just values from 0 to our calendar columns minus one so this result in the parenthesis here will be always from 0 1 2 3 4 5 6 and then again 0 4 5 and 1 2 3 4 5 6 and so we always multiply this x steps just with a value from 0 to 6 so we will go over our x-axis in the right way and the stroke wave is just a little um extra offset here and so that the value does not get wall on the grid and for this text position y we can't use the modulo operator because we first want to draw all the values on the horizontal line and this result here should only increase by one if we go to the next line in a vertical way so if this I here is 7 and the calendar columns are also seven then this will be one the first time and this is also right because if I is 7 we are on day 8 and we are in the next line then we will multiply this of course with with our y steps because these are this this is the step size we go from the top to the bottom and we apply this little offset our text Heights and the stroke width divided by two because we don't want to draw the text at the grid lines and we also need to add the text height here because the text gets starts drawing at the bottom and then it gets drawn to the top all right okay this was it for the complex parts of drawing this different numbers now we can say drawcontext dot canvas dot native canvas dot apply and we can then draw the text draw text for the text we will simply pass I plus 1 because we are always um one day above our current iteration I because I starts with zero and then we will pass the text position X the text position Y and also we will apply a page here paints.apply the text size will be our text Heights and the color will be white dot 2 RGB and we will also make this bold so we will set this to true and then we can launch the application and have a look at it to see if everything worked and I think this looks great all right okay this was it for drawing the calendar now we will have a look and implement the logic for our animation and clicks and the click processing so let's go above to our canvas and first of all we need some State bars we need the canvas size as the State Bar because we later need to access it inside the canvas modifier and there we don't have access to to decide the title with so we need to make this a state bar here which starts with mutable state of offset.0 down here we can then set the state one to Canvas size is equal to offset canvas with and canvas height like this then we need additional State bars we need a VAR click any major offset so where the user actually clicked this will be by default offset.0 as well and we need a VAR animation radius this will be the radius we will animate later so when the user clicks on a specific day then the radius of a circle will be expanded until it gets clipped off of the border of the specific day item this will be mutable state of and 0 by default the last thing we need is a curating scope to launch our animation later and we can get the scope from remember curating scope so that it is also scoped to decomposable's Lifetime now here where the canvas modifier is we can say pointer input and pass true here and then we can detect type gestures and we will need the on Tab methods which will provide an offset for us so this offset is the exact position where the user actually tapped the concept here is really easy to get a day we will just need to calculate the column and the row and then we get the corresponding day with an additional little calculation but we need to consider some things when we calculate this column and row we will say well column is equal to offset.x divided by our canvas size dot with and why don't we have access here oh okay I think I know what this means and we need the canvas width here but we defined this as an offset here this needs to be of course size.0 because we also want to save the canvas size here and in here where we actually initialize it we also need to change this to a size and then we have access to the canvas size.wiff and we need to multiply this with the calendar columns and map this to an integer and say Blue Swan for the row we can simply copy and paste this here and rename this to row the offset will be this time offset.y the canvas size dot Heights and we take the calendar rows here with the same principle to calculate the row so how does this work this will calculate the relative amount of the user click on the x-axis this value can go from 0 to 1.0 and we multiply this then with our calendar columns so that we get the corresponding click on the column then this two integer will cut off the commas but even if we have something like 5.99 then this will cut off the nine nines and this is why we use this plus one after that and the same principle for this row calculation but of course this time for the offset.wi the canvasized that height and the calendar rows because we are now talking about the vertical relative amount of the user click and again this plus one is also applied because if we are in the first column or row then that this calculation will result in zero and so like in a for Loop we start with zero to a calendar rows minus one or to count in the columns minus one and to get the right column and row if we want this from one to seven for example or one to five when we have a look at the rows we need to make this plus one now we can calculate the day which we will get from my column plus row minus one multiplied with our calendar columns okay to understand this we could just make a little example here let's assume the user clicked on the second column and on the first row then this column would be two and this row would be one this would result in 0 multiplied with the calendar columns does not take any effect so we would have day two then let's let's take another example if we would click on the first column and the second row then this was would be one the row would be two minus one would be one multiplied with seven this would result in day number eight because the second row and the First Column is day number eight okay all right I hope this gots clear then we can say if they is less or equal then our calendar inputs.size so if today the user actually clicked was really on the calendar because if we have a look at the application then on the right at the bottom there are four empty grids items here and we don't want to detect temperatures just if the user clicks on them so this is about this if condition here is about and then we can invoke on the click and pass the day and we will say the click animation offset is equal to offset after that we can use our scope.launch to get accuratine scope where we can start the animation animate 0f to 225 F this will be the target value of how big the click event actually should be I will talk about this value later and the animation spec will be between 300 for example and then you can open this and I hope you can see this we get the value here and the second parameter isn't needed and in here we can then say animation radius is equal to Value this animation radius is our value our state bar which we defined above and we can pass this now inside um another draw element in our canvas to make this animation actually triggering all right okay I was quickly at the hairdresser and now we can finish this off we can copy this row and column formula and paste it down here because we also need to access the column and row for our animation in our draw scope but for the offset we will say click animation offset.x and here click animation offsets dot Y and then we need to define a path because we need to clip this animation to a specific path so that this animation does not exceed the grid item of our clicked day and this path will be exactly the grid item so we will say well path is equal to path dot apply in here we will now Define the path of our grid item so a rectangle path and we first need to move the cursor to a specific point where we want to start drawing this will be column -1 multiplied with the X steps and for the Y value we will say rho minus small multiplied with the Y steps so this will be the top left of our grid item after that we can draw our first line which goes from the top left to the top right this is why we say column without the minus one multiplied with the X steps and for the Y value we still have rho minus 1 multiplied with the Y steps so this will draw a line from the top left to the top right of our grid item the next line will be a column multiplied with X steps as well but now we will go from the top to the bottom so we will say row o multiplied with Y steps and then we are at the bottom right the next line will go from the bottom right to the bottom left so we will say this time column -1 multiplied with X steps and here row multiplied with Y steps as well after that we can close the path for the last line we don't need to define the 12 for the last line we can simply say close and then we have our path of the grid item we can apply a clip path function now and pass our defined path and everything that gets drawn inside the straw scope will be clipped to this specific path so it won't exceed the path's borders in here we can then draw a circle this circle will have a brush and this brush will be a radial gradient for the colors we will pass a list of colors this will be orange dot copy 0.8 F so that we have a little bit of a transparent here and the second color will be orange dot copy 0.2 F so even more transparency here and the center will be our click animation offset so the exact point where the user actually clicked so if he Clicks in a grid item at the bottom then the animation starts from the bottom and expands and builds the whole of your the radius will be animation radius plus 0.1 F because this animation radius is 0 by default and our app would crash if we pass zero for the radius here so we add this little loading value and this is for the brush drawing this is not the draw Circle this is just that the brush our radial gradient looks uh like the user really clicked on this positioner so the gradient starts from there and then we also need of course the circle drawing and this is the same principle here we have our animation radius plus 0.1 f for the radius and for the offset now for the center we pass the click animation offset alright okay this was actually it for the canvas drawing let's go to our main activity and make the click item also take effect on the UI so that we get the list of the different to-do items when we click on the specific calendar elements we will say well clicked calendar LM fine remember mutable stayed off and we need to define a type here this will be of pipe calendar input but it's optional because by default there's no clicked item and the default value will be null this on the click Lambda function will provide us the day the user actually clicked we can name this today and set our clicked elements of the calendar clicked calendar element is equal to calendar input list DOT first and this first will just return the first element which matches the given predicate so it's the date is equal to day below our calendar composable we will Define a column takes a modifier which builds the Maxwell the padding will be 10 DP and the alignment will be alignment Dot Center in here we will just list all the to-do items of our click calendar elements in your projects you should maybe apply a better UI but this is just to show you that we get access to this clicked item and that we can list the different to-do items we can say clicked calendar element to Do's dot for each this needs to be an optional chaining because this clicked calendar element is not by default and it shouldn't show a text if the user did not click on a calendar item yet for the text we can say if it's Dodge contains Bay it should just show it and else we want to apply a little line before the text so that we can list up the different to do items for the color we will pass whites the font weights will be semi balls and the font size will also depend on if it's currently the day or at to-do list item if each Dutch contains they again then we will set this to 25 SP and otherwise to 18 SP now we can try this out I have enabled my mouse so that you can see where I'm clicking I will click on 17 16 23 and I think this works very well let's also zoom in a little bit so that we can see that the animation starts and the gradients start actually goes from our Mouse click if I click on 17 at the bottom left then you can see that the circle expands from there and also our gradient because at the bottom left it's more orange than at the bottom right and let's also click on different positions yeah then you can see this looks very cool and very smoothly let me also quickly show you one more thing in our animation definition here where we Define this in the curating scope we can change this to 105 for example and launch this again you will see that that Circle does not fill the grid item anymore because the target value is too low here so always make sure that this target value is high enough to fill your grid item but on the other hand if you expand this or increase this to 500 and launch this again then you can see that the gradient does not work that good anymore because now the whole field is just orange because the circle is very big and this is just a little part of the circle so always be sure to choose a good Target value here to make this work with the gradient and so that it does not get too big all right okay this was it for this video I hope you enjoyed it and in case you want to see more about checkpoint compose and canvas then check out my YouTube channel or leave a subscribe because I will continue making some such videos sometimes on more basic stuff and sometimes more advanced stuff so CS then
Info
Channel: K Apps
Views: 6,359
Rating: undefined out of 5
Keywords: Jetpack Compose, Canvas, Jetpack Compose Canvas, Android Canvas, Android Jetpack Compse, Compose Canvas, Kotlin Canvas, Kotlin Android, Android User Experience, Jetpack Compose State, JetpackCompose, JetpackCompose Canvas, Android JetpackCompose, Android Calendar, Jetpack Compose Calendar, Android Studio, Android Studio Canvas, Android Studio Calendar
Id: QS-iOdm0pMs
Channel Id: undefined
Length: 30min 6sec (1806 seconds)
Published: Sat Nov 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.