@@ -19,50 +19,67 @@ import androidx.compose.ui.text.style.TextAlign
1919import androidx.compose.ui.tooling.preview.Preview
2020import androidx.compose.ui.unit.dp
2121
22+ private const val BYTES_PER_ROW = 16
23+ private val OFFSET_WIDTH = 90 .dp
24+ private val HEX_CELL_WIDTH = 25 .dp
25+ private val ASCII_CELL_WIDTH = 12 .dp
26+
2227@ExperimentalFoundationApi
2328@Composable
2429fun HexView (bytes : ByteArray ) {
25- val splitted by remember {
26- derivedStateOf { (bytes.toList().chunked(8 )) }
30+ val rows by remember {
31+ derivedStateOf {
32+ bytes.toList().chunked(BYTES_PER_ROW ).mapIndexed { idx, chunk ->
33+ Pair (idx * BYTES_PER_ROW , chunk)
34+ }
35+ }
2736 }
2837
29-
3038 LazyColumn (Modifier .horizontalScroll(rememberScrollState())) {
3139 stickyHeader {
3240 HexViewHeader ()
3341 }
34- items(splitted ) { item ->
35- HexViewRow (item )
42+ items(rows ) { (offset, chunk) ->
43+ HexViewRow (offset, chunk )
3644 }
3745 }
38-
3946}
4047
4148@Composable
4249fun HexViewHeader () {
4350 Row (Modifier .height(IntrinsicSize .Min )) {
44- for (v in 0 .. 7 ) {
51+ // Offset column header
52+ Text (
53+ text = " Offset" ,
54+ modifier = Modifier
55+ .width(OFFSET_WIDTH )
56+ .fillMaxHeight()
57+ .background(Color .White ),
58+ textAlign = TextAlign .Center ,
59+ fontWeight = FontWeight .ExtraBold ,
60+ color = Color .DarkGray
61+ )
62+ Spacer (modifier = Modifier .width(4 .dp).fillMaxHeight())
63+ // Hex column headers 00..0F
64+ for (v in 0 until BYTES_PER_ROW ) {
4565 Text (
4666 text = String .format(" %02X" , v),
4767 modifier = Modifier
48- .width(25 .dp )
68+ .width(HEX_CELL_WIDTH )
4969 .fillMaxHeight()
5070 .background(Color .White ),
5171 textAlign = TextAlign .Center ,
5272 fontWeight = FontWeight .ExtraBold ,
5373 color = Color .Blue
5474 )
5575 }
56- Spacer (
57- modifier = Modifier
58- .fillMaxHeight()
59- .width(10 .dp)
60- )
61- for (v in 0 .. 7 ) {
76+ Spacer (modifier = Modifier .width(8 .dp).fillMaxHeight())
77+ // ASCII column headers
78+ for (v in 0 until BYTES_PER_ROW ) {
6279 Text (
63- text = String .format(" %02X " , v),
80+ text = String .format(" %X " , v),
6481 modifier = Modifier
65- .width(20 .dp )
82+ .width(ASCII_CELL_WIDTH )
6683 .fillMaxHeight()
6784 .background(Color .White ),
6885 textAlign = TextAlign .Center ,
@@ -71,58 +88,56 @@ fun HexViewHeader() {
7188 )
7289 }
7390 }
74-
7591}
7692
7793@Composable
78- private fun HexViewRow (item : List <Byte >) {
79- Row (
80- Modifier .height(IntrinsicSize .Min )
81- ) {
94+ private fun HexViewRow (offset : Int , item : List <Byte >) {
95+ Row (Modifier .height(IntrinsicSize .Min )) {
96+ // Offset column
97+ Text (
98+ text = String .format(" 0x%08X" , offset),
99+ modifier = Modifier
100+ .width(OFFSET_WIDTH )
101+ .fillMaxHeight()
102+ .background(Color .White ),
103+ textAlign = TextAlign .Center ,
104+ color = Color .DarkGray
105+ )
106+ Spacer (modifier = Modifier .width(4 .dp).fillMaxHeight())
107+ // Hex cells
82108 for (v in item) {
83109 Text (
84110 text = String .format(" %02X" , v),
85111 modifier = Modifier
86- .width(25 .dp )
112+ .width(HEX_CELL_WIDTH )
87113 .fillMaxHeight()
88114 .background(Color .White ),
89115 textAlign = TextAlign .Center
90116 )
91117 }
92- for (i in 0 until 8 - item.size) {
118+ // Padding for incomplete last row
119+ for (i in 0 until BYTES_PER_ROW - item.size) {
93120 Text (
94- text = " " ,
121+ text = " " ,
95122 modifier = Modifier
96- .background( Color . White )
123+ .width( HEX_CELL_WIDTH )
97124 .fillMaxHeight()
98- .width( 25 .dp )
125+ .background( Color . White )
99126 )
100127 }
101- Spacer (
102- modifier = Modifier
103- .fillMaxHeight()
104- .width(10 .dp)
105- )
128+ Spacer (modifier = Modifier .width(8 .dp).fillMaxHeight())
129+ // ASCII cells
106130 for (v in item) {
107131 val c = v.toInt().toChar()
108132 Text (
109133 text = if (isPrintableChar(c)) c.toString() else " ." ,
110134 modifier = Modifier
111- .width(20 .dp )
135+ .width(ASCII_CELL_WIDTH )
112136 .fillMaxHeight()
113137 .background(Color .White ),
114138 textAlign = TextAlign .Center
115139 )
116140 }
117- for (i in 0 until 8 - item.size) {
118- Text (
119- text = " " ,
120- modifier = Modifier
121- .background(Color .White )
122- .fillMaxHeight()
123- .width(20 .dp)
124- )
125- }
126141 }
127142}
128143
@@ -137,16 +152,11 @@ fun isPrintableChar(c: Char): Boolean {
137152fun HexPreview () {
138153 HexView (
139154 bytes = byteArrayOf(
140- 0xFF .toByte(),
141- 0x12 .toByte(),
142- 0x13 .toByte(),
143- 0x11 .toByte(),
144- 0x40 .toByte(),
145- 0x33 .toByte(),
146- 0x65 .toByte(),
147- 0x55 .toByte(),
148- 0x70 .toByte(),
149- 0x59 .toByte()
155+ 0xFF .toByte(), 0x12 .toByte(), 0x13 .toByte(), 0x11 .toByte(),
156+ 0x40 .toByte(), 0x33 .toByte(), 0x65 .toByte(), 0x55 .toByte(),
157+ 0x70 .toByte(), 0x59 .toByte(), 0x4A .toByte(), 0x2B .toByte(),
158+ 0x1C .toByte(), 0x3D .toByte(), 0xEE .toByte(), 0x7F .toByte(),
159+ 0x00 .toByte(), 0xAB .toByte()
150160 )
151161 )
152162}
0 commit comments