{"id":4079,"date":"2025-12-09T17:21:58","date_gmt":"2025-12-09T17:21:58","guid":{"rendered":"https:\/\/alsaeeddev.com\/admin-wordpress\/?p=4079"},"modified":"2025-12-09T17:33:02","modified_gmt":"2025-12-09T17:33:02","slug":"how-to-build-blood-pressure-app-android-ui-using-jetpack-compose","status":"publish","type":"post","link":"https:\/\/alsaeeddev.com\/shop\/how-to-build-blood-pressure-app-android-ui-using-jetpack-compose\/","title":{"rendered":"How to Build a Real-Time Blood Pressure App Android UI Using Jetpack Compose"},"content":{"rendered":"<p>Modern health applications\u2014whether you&#8217;re building a <strong>blood pressure app Android<\/strong>, an <strong>ECG app Android<\/strong>, or a <strong>heart rate monitor Android<\/strong>\u2014require interfaces that are clean, smooth, and capable of updating in real time. With Jetpack Compose, Android developers can design advanced animated dashboards using only a few composable functions.<\/p>\n<p>In this guide, we\u2019ll walk through a complete real-time vital monitoring UI built entirely with <strong>Canvas<\/strong>, <strong>animations<\/strong>, and <strong>Jetpack Compose<\/strong>.<br \/>\nThe final setup includes:<\/p>\n<ul>\n<li>A <strong>pressure gauge<\/strong> (mmHg) for blood pressure visualization<\/li>\n<li>A real-time <strong>ECG waveform<\/strong> renderer<\/li>\n<li>A <strong>vital simulator<\/strong> that generates dynamic heartbeat, SpO\u2082, and pressure values<\/li>\n<\/ul>\n<p>If you\u2019re creating a health monitoring interface, these components provide a great foundation.<\/p>\n<h4><strong>1. The Blood Pressure Gauge&#8217;s (PressureGauge) user interface<\/strong><\/h4>\n<p>The PressureGauge composable makes a round gauge that is fully animated and looks like the dials on professional sphygmomanometers used in clinics.<br \/>\nImportant parts of the gauge<\/p>\n<ul>\n<li>\u00a0The needle moves smoothly.<\/li>\n<li>\u00a0It ticks every 10 mmHg.<\/li>\n<li>\u00a0Major ticks every 20 mmHg.<\/li>\n<li>\u00a0A soft radial gradient background.<\/li>\n<li>A 270\u00b0 sweep (\u2013135\u00b0 to +135\u00b0), just like a medical pressure meter.<\/li>\n<\/ul>\n<p>The needle moves smoothly toward the new pressure value when you use animateFloatAsState(). This makes it feel like a real machine, which is great for the UI of an Android blood pressure app.<\/p>\n<p><strong>PressureGauge Code<\/strong><\/p>\n<pre><code class=\"language-java\">  \r\n@Composable\r\nfun PressureGauge(\r\n    pressure: Float,\r\n    maxPressure: Float = 300f,\r\n    modifier: Modifier = Modifier\r\n) {\r\n    val animatedPressure by animateFloatAsState(\r\n        targetValue = pressure,\r\n        animationSpec = tween(800, easing = LinearOutSlowInEasing)\r\n    )\r\n\r\n    val size = 260.dp\r\n    val center = size \/ 2\r\n\r\n    Box(\r\n        modifier = modifier\r\n            .size(size)\r\n            .padding(12.dp),\r\n        contentAlignment = Alignment.Center\r\n    ) {\r\n        Canvas(modifier = Modifier.fillMaxSize()) {\r\n\r\n            val w = this.size.width\r\n            val h = this.size.height\r\n            val cx = w \/ 2\r\n            val cy = h \/ 2\r\n\r\n            val rotation = -135f + (animatedPressure.coerceAtMost(maxPressure) \/ maxPressure) * 270f\r\n\r\n            \/\/ BACKGROUND GRADIENT\r\n            drawCircle(\r\n                brush = Brush.radialGradient(\r\n                    colors = listOf(Color.White, Color(0xFFE2E8F0))\r\n                ),\r\n                radius = w * 0.45f,\r\n                center = Offset(cx, cy)\r\n            )\r\n\r\n            \/\/ TICKS\r\n            for (i in 0..maxPressure.toInt() step 10) {\r\n                val angle = -135f + (i \/ maxPressure) * 270f\r\n                val rad = Math.toRadians((angle - 90).toDouble())\r\n\r\n                val major = i % 20 == 0\r\n                val length = if (major) 18f else 10f\r\n                val width = if (major) 2f else 1f\r\n\r\n                val rOuter = w * 0.4f\r\n                val rInner = rOuter - length\r\n\r\n                val x1 = cx + rOuter * cos(rad).toFloat()\r\n                val y1 = cy + rOuter * sin(rad).toFloat()\r\n                val x2 = cx + rInner * cos(rad).toFloat()\r\n                val y2 = cy + rInner * sin(rad).toFloat()\r\n\r\n                drawLine(\r\n                    color = if (major) Color(0xFF334155) else Color(0xFF94A3B8),\r\n                    start = Offset(x1, y1), end = Offset(x2, y2),\r\n                    strokeWidth = width\r\n                )\r\n            }\r\n\r\n            \/\/ NEEDLE\r\n            rotate(rotation, pivot = Offset(cx, cy)) {\r\n                drawLine(\r\n                    start = Offset(cx, cy),\r\n                    end = Offset(cx, cy - w * 0.35f),\r\n                    color = Color(0xFFEF4444),\r\n                    strokeWidth = 6f,\r\n                    cap = StrokeCap.Round\r\n                )\r\n                drawCircle(\r\n                    color = Color(0xFFEF4444),\r\n                    center = Offset(cx, cy),\r\n                    radius = 10f\r\n                )\r\n            }\r\n        }\r\n    }\r\n\r\n    Column(horizontalAlignment = Alignment.CenterHorizontally) {\r\n        Text(\r\n            text = animatedPressure.toInt().toString(),\r\n            fontSize = 34.sp,\r\n            fontWeight = FontWeight.Bold,\r\n            color = Color(0xFF1E293B)\r\n        )\r\n        Text(\r\n            text = \"mmHg\",\r\n            color = Color(0xFF64748B),\r\n            fontSize = 12.sp\r\n        )\r\n    }\r\n}\r\n <\/code><\/pre>\n<h5><strong>2. PulseECG \u2013 A real-time renderer for ECG waveforms<\/strong><\/h5>\n<p>The waveform is the most important visual part of an ECG app for Android. The PulseECG composable makes it look like an ECG trace is moving by constantly moving a list of points.<br \/>\n<strong>How it works<\/strong><br \/>\nKeeps a list of 120 points that keeps changing<br \/>\nChanges values based on two conditions:<br \/>\nactive: ECG is working<br \/>\nbeating: heartbeats<br \/>\nMakes a dark grid that looks like a medical one<br \/>\nDraws a glowing red ECG path to make it look real<br \/>\nIt looks a lot like real ECG monitor output and can easily take real medical data.<\/p>\n<p><strong>PulseECG Code<\/strong><\/p>\n<pre><code class=\"language-java\">  \r\n@Composable\r\nfun PulseECG(\r\n    active: Boolean,\r\n    beating: Boolean,\r\n    modifier: Modifier = Modifier\r\n) {\r\n    var points by remember { mutableStateOf(List(120) { 50f }) }\r\n    var tick by remember { mutableStateOf(0) }\r\n\r\n    LaunchedEffect(active, beating) {\r\n        while (true) {\r\n            delay(40)\r\n\r\n            val new = points.toMutableList()\r\n            new.removeAt(0)\r\n\r\n            val updated = when {\r\n                !active -&gt; 50f\r\n                !beating -&gt; 50f + (Math.random().toFloat() - 0.5f) * 8f\r\n                else -&gt; when (tick % 12) {\r\n                    0 -&gt; 50f\r\n                    1 -&gt; 30f\r\n                    2 -&gt; 95f\r\n                    3 -&gt; 10f\r\n                    4 -&gt; 60f\r\n                    else -&gt; 50f\r\n                }\r\n            }\r\n            new.add(updated)\r\n            points = new\r\n\r\n            if (beating) tick++\r\n        }\r\n    }\r\n\r\n    Canvas(\r\n        modifier = modifier\r\n            .fillMaxWidth()\r\n            .height(110.dp)\r\n            .background(Color(0xFF0F172A))\r\n            .padding(4.dp)\r\n    ) {\r\n        val w = size.width\r\n        val h = size.height\r\n\r\n        \/\/ GRID\r\n        drawRect(Color(0xFF1E293B))\r\n        for (x in 0 until w.toInt() step 20)\r\n            drawLine(Color(0xFF334155), Offset(x.toFloat(), 0f), Offset(x.toFloat(), h))\r\n        for (y in 0 until h.toInt() step 20)\r\n            drawLine(Color(0xFF334155), Offset(0f, y.toFloat()), Offset(w, y.toFloat()))\r\n\r\n        \/\/ ECG line\r\n        val path = Path()\r\n        points.forEachIndexed { i, v -&gt;\r\n            val x = (i \/ points.size.toFloat()) * w\r\n            val y = h - (v \/ 100f) * h\r\n            if (i == 0) path.moveTo(x, y) else path.lineTo(x, y)\r\n        }\r\n\r\n        \/\/ Glow\r\n        drawPath(\r\n            path = path,\r\n            color = Color(0xFFEF4444).copy(alpha = 0.4f),\r\n            style = Stroke(width = 8f)\r\n        )\r\n\r\n        drawPath(\r\n            path = path,\r\n            color = Color(0xFFEF4444),\r\n            style = Stroke(width = 3f)\r\n        )\r\n\r\n    }\r\n}\r\n <\/code><\/pre>\n<h5><strong>3. VitalSimulator \u2013 Generating Real-Time Readings<\/strong><\/h5>\n<p>For demo purposes\u2014or previewing UI\u2014you can use VitalSimulator, a small composable that generates random:<\/p>\n<ul>\n<li>Blood pressure<\/li>\n<li>Heart rate (BPM)<\/li>\n<li>SpO\u2082 oxygen level<\/li>\n<\/ul>\n<p>This is especially useful while building a <strong>heart rate monitor Android<\/strong> interface.<\/p>\n<p><strong>VitalSimulator Code<\/strong><\/p>\n<pre><code class=\"language-java\"> \r\n@Composable\r\nfun VitalSimulator(): Triple&lt;Float, Float, Float&gt; {\r\n    var pressure by remember { mutableStateOf(120f) }\r\n    var bpm by remember { mutableStateOf(75f) }\r\n    var spo2 by remember { mutableStateOf(97f) }\r\n\r\n    LaunchedEffect(Unit) {\r\n        while (true) {\r\n            delay(1500)\r\n            pressure = (110..135).random().toFloat()\r\n            bpm = (72..90).random().toFloat()\r\n            spo2 = (96..99).random().toFloat()\r\n        }\r\n    }\r\n\r\n    return Triple(pressure, bpm, spo2)\r\n}\r\n<\/code><\/pre>\n<h6><strong>Putting It All Together<\/strong><\/h6>\n<p>By combining these composables, you can build a polished dashboard showing:<\/p>\n<ul>\n<li>Animated blood pressure<\/li>\n<li>Real-time ECG waveform<\/li>\n<li>BPM and SpO\u2082 levels<\/li>\n<\/ul>\n<p>This is an excellent base for medical-style dashboards or consumer wellness applications.<\/p>\n<hr \/>\n<p><iframe loading=\"lazy\" title=\"Android Jetpack Compose Vital Sign Monitoring UI | Blood Pressure |  ECG | Heart Rate #shorts\" width=\"540\" height=\"960\" src=\"https:\/\/www.youtube.com\/embed\/_HxUlgd98Wo?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<hr \/>\n<p><!-- Download Button --><br \/>\n<a href=\"https:\/\/github.com\/alsaeeddev\/blood-pressure-app-android-ui\/archive\/refs\/heads\/main.zip\">Download Source Code<\/a><\/p>\n<h2><strong>Final Thoughts<\/strong><\/h2>\n<p>Jetpack Compose makes it possible to build real-time health monitoring dashboards with only a few clean, efficient composables. Whether you&#8217;re working on a <strong>blood pressure app Android<\/strong>, an <strong>ECG app Android<\/strong>, or a <strong>heart rate monitor Android<\/strong>, these components give you a professional, animated, and scalable UI foundation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern health applications\u2014whether you&#8217;re building a blood pressure app Android, an ECG app Android, or a heart rate monitor Android\u2014require interfaces that are clean, smooth, and capable of updating in real time. With Jetpack Compose, Android developers can design advanced animated dashboards using only a few composable functions. In this guide, we\u2019ll walk through a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4098,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,116,164],"tags":[169,225,229,238,102,224,228,232,226,236,233,227,105,230,235,231,239,237,234],"class_list":["post-4079","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-kotlin","category-source-codes","tag-android-canvas-drawing","tag-android-custom-view","tag-android-health-app","tag-android-medical-dashboard","tag-android-ui-design","tag-blood-pressure-app-android","tag-blood-pressure-monitor-app","tag-ecg-animation-android","tag-ecg-app-android","tag-health-tracking-app-android","tag-heart-rate-monitor-android","tag-heart-rate-monitor-android-source-code","tag-jetpack-compose-tutorial","tag-jetpack-compose-ui","tag-kotlin-android-project","tag-medical-app-ui-android","tag-mobile-health-app-development","tag-patient-monitoring-ui","tag-real-time-vital-signs-android"],"_links":{"self":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/4079","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/comments?post=4079"}],"version-history":[{"count":8,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/4079\/revisions"}],"predecessor-version":[{"id":4103,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/4079\/revisions\/4103"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/media\/4098"}],"wp:attachment":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/media?parent=4079"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/categories?post=4079"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/tags?post=4079"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}