[Android/Compose] 리스트뷰 구현

찌니·2022년 8월 11일
0

Android(Compose)

목록 보기
10/12

컴포즈가 아닌 xml로 구현할때는 세상 귀찮았던 리스트뷰 !!!!
컴포즈로 구현해봅시다

컴포즈의 가장 큰 장점은 변화에 자유롭다는 것.
데이터의 변화에 바로바로 반응할 수 있다는 점이 가장 큰 장점이지 않을까 싶다.

임시적으로 보여주기 위해 일단은 뷰모델에 더미데이터를 만들어뒀지만 일반적으로는 데이터 베이스에서 데이터를 불러와 리스트로 노출해줄때 적용할 수 있다

MainActivity.kt


    private val viewModel by viewModels<ViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TestTheme {
                Surface(
                    modifier = Modifier.fillMaxSize()
                ) {
                    MainScreen(viewModel)
                }
            }
        }
    }
}


@Composable
fun MainScreen(viewModel: ViewModel) {
    val scaffoldState = rememberScaffoldState()
	val scope = rememberCoroutineScope()

    Scaffold(
        scaffoldState = scaffoldState,
        topBar = {
            TopAppBar(
                title = {
                },
                actions = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Filled.Send, contentDescription = "")
                    }
                },
                navigationIcon = {
                    IconButton(onClick = {
                        scope.launch {
                            scaffoldState.drawerState.open()
                        }
                    }) {
                        Icon(Icons.Filled.Menu, contentDescription = "")
                    }
                },
                modifier = Modifier.fillMaxWidth(),
                backgroundColor = MaterialTheme.colors.background,
                elevation = 0.dp
            )
        }
    ) {
        Column(
            modifier = Modifier
                .padding(it)
                .fillMaxSize()
        ) {
            ListScreen() // 리스트 뷰
        }
    }
}

ListView.kt

  • 메인에서 호출하는 리스트뷰
@Composable
fun ListScreen(
) {
    Column() {
        Text(text = "RowList", modifier = Modifier.padding(start = 20.dp))
        RowList(viewModel.testData.collectAsState())
        Text(text = "GridList", modifier = Modifier.padding(start = 20.dp))
        GridList(viewModel.testData.collectAsState())
    }
}

@Composable
fun GridList(data: State<ArrayList<TestData>?>) { // 그리드뷰
    val scrollState = rememberLazyGridState()

    LazyVerticalGrid( //  lazy는 지연 목록으로, 데이터의 수를 모르는 경우 맞춰서 변할 수 있음
        state = scrollState,
        columns = GridCells.Fixed(2),
        verticalArrangement = Arrangement.spacedBy(40.dp),
        horizontalArrangement = Arrangement.spacedBy(40.dp),
        modifier = Modifier
            .padding(top = 10.dp, start = 30.dp, end = 30.dp),
        userScrollEnabled = true
    ) {
        data.value?.let {
            items(it) { item ->
            // 데이터 마다 카드(item) 생성
                GridItemCard(data = item)
            }
        }
    }
}

@Composable
fun RowList(data: State<ArrayList<TestData>?>) {
    LazyRow(
        modifier = Modifier
            .fillMaxWidth()
            .horizontalScroll(rememberScrollState())
            .padding(start = 30.dp, end = 30.dp, top = 10.dp, bottom = 30.dp)
    ) {
        data.value?.let {
            items(it) { item ->
                RowItemCard(item)
            }
        }
    }
}

ItemView.kt

  • 리스트 내부 아이템 하나하나를 나타내는 뷰
@Composable
fun GridItemCard(data: TestData) { 
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .height(230.dp),
        shape = MaterialTheme.shapes.small.copy(CornerSize(20.dp)),
        elevation = 10.dp
    ) {
        Column() {
            val modifier = Modifier.fillMaxHeight(0.6f)
            ItemImage(data.image, data.gender)
            ItemText(data)
        }
    }
}

@Composable
fun RowItemCard(data: TestData) {
    Card(
        modifier = Modifier
            .padding(end = 20.dp)
            .fillMaxWidth(),
        shape = MaterialTheme.shapes.small.copy(CornerSize(20.dp)),
        elevation = 10.dp
    ) {
        Surface(shape = MaterialTheme.shapes.small.copy(CornerSize(20.dp))) {
            Row(verticalAlignment = Alignment.Bottom) {
                ItemImage(data.image, data.gender)
                ItemText(data)
            }
        }
    }
}

@Composable
fun ItemText(data: TestData) {
    Column(Modifier.padding(10.dp)) {
        Text(text = data.name, fontSize = 15.sp, color = Color.Black, modifier = Modifier.padding(bottom = 10.dp))
        Text(text = data.age.toString(), fontSize = 13.sp, color = Color.Black)
        Text(text = data.gender, fontSize = 13.sp, color = Color.Black)
        Text(
            text = if (data.student) "student"
            else "not student",
            fontSize = 13.sp
        )
    }
}

@Composable
fun ItemImage(image: String, gender: String) {
    Surface(shape = MaterialTheme.shapes.small.copy(CornerSize(20.dp))) {
        AsyncImage(
            model = ImageRequest.Builder(LocalContext.current)
                .data(image)
                .crossfade(true)
                .build(),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            placeholder = painterResource(
                when (gender) {
                    "male" -> com.example.test.R.drawable.man
                    else -> com.example.test.R.drawable.woman
                }
            ),
            modifier = Modifier.size(100.dp)
        )
    }
}
profile
찌니's develog

0개의 댓글