I m new To Jetpack Compose , i'm trying to create a Proxy list app , used lazy column to list proxies but its now showing .. app runs successfully but result not getting , Give Me a Solution . Thx
Lib : https://github.com/gumify/hiper
#Preview
#Composable
fun App(){
val hiper = Hiper.getInstance().async() // for asynchronous requests
val Proxies = remember {mutableStateListOf<String>() }
Surface(modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()) {
Column(modifier = Modifier
.background(Color.Blue)
.height(20.dp),
horizontalAlignment = Alignment.CenterHorizontally) {
Button (
modifier = Modifier.padding(all = Dp(10F)),
onClick = {
hiper.get("http://spys.me/proxy.txt") { response ->
if (response.isSuccessful) {
val lines = response.text.toString().split("\n")
for (line in lines) {
Proxies.add(line)
}
}
}
}) { Text(text = "Get Proxies") }
LazyColumn( modifier = Modifier.background( color = Color.Gray)){
items(Proxies){item ->
Text(text = item)
}
}
}
}
}
}
Related
I'm new to jetpack compose and I am just looking for a way to add and delete items from a lazyVerticalGrid using jetpack compose from a pop-up menu. Nothing complicated, just simple code to make me easily understand what I have to do
This is pretty easy as other LazyLists. You need to have a list that you can trigger recomposition after delete, add or update and use unique keys to not recompose your entire list and limit recomposition to a range of items.
val list = remember { mutableStateListOf<Snack>() }
You can remove or add inside you menu by changing this list
Adding, removing items or replacing any items with new one, to update you need to pass a new instance of object, will trigger recomposition
#Composable
private fun GridExample() {
val scrollState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
val list = remember { mutableStateListOf<Snack>() }
Column {
LazyVerticalGrid(
contentPadding = PaddingValues(12.dp),
modifier = Modifier
.weight(1f)
.background(backgroundColor),
columns = GridCells.Fixed(3),
content = {
items(items = list,
key = { snack: Snack ->
snack.name
}) { snack: Snack ->
GridSnackCard(snack = snack)
}
}
)
Row(
modifier = Modifier.padding( 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(
modifier = Modifier.weight(1f),
onClick = {
if (list.size < snacks.size) {
list.add(snacks[list.size])
}
},
shape = RoundedCornerShape(8.dp)
) {
Text(text = "Add")
}
Spacer(modifier = Modifier.width(10.dp))
Button(
modifier = Modifier.weight(1f),
onClick = {
if (list.size > 0) {
list.removeLast()
}
},
shape = RoundedCornerShape(8.dp)
) {
Text(text = "Remove")
}
}
}
}
I have dialog in compose:
#Composable
fun testgtt() {
val saveDialogState = remember { mutableStateOf(false) }
Button(onClick = { saveDialogState.value = true }, modifier = Modifier.testTag(PLACE_TAG)) {
Text(text = "helllow")
}
Dialog(onDismissRequest = { saveDialogState.value = false }) {
Text(text = "helllow",modifier = Modifier.testTag(BUTTON_TAG))
}
}
and want to test it:
#Test
fun das(){
composeTestRule.setContent {
TerTheme {
testgtt()
}
}
composeTestRule.onRoot(useUnmergedTree = true).printToLog("currentLabelExists")
composeTestRule.onNodeWithTag(PLACE_TAG).performClick()
composeTestRule.onNodeWithTag(BUTTON_TAG).assertIsDisplayed()
}
but I get this error:
java.lang.AssertionError: Failed: assertExists.
Reason: Expected exactly '1' node but found '2' nodes that satisfy: (isRoot)
Nodes found:
1) Node #1 at (l=0.0, t=0.0, r=206.0, b=126.0)px
Has 1 child
2) Node #78 at (l=0.0, t=0.0, r=116.0, b=49.0)px
Has 1 child
Inspite of the fact that I see the Dialog itself.
The reason for this error is the line: composeTestRule.onRoot(useUnmergedTree = true).printToLog("currentLabelExists")
onRoot expects a single node, but i suspect both the containing view and the dialog each return their own root (Speculation)
A possible workaround is to instead print both root trees using something like
composeTestRule.onAllNodes(isRoot()).printToLog("currentLabelExists")
use navigation component:
#Composable
fun de(){
val navController = rememberNavController()
Scaffold { innerPadding ->
NavHost(navController, "home", Modifier.padding(innerPadding)) {
composable("home") {
// This content fills the area provided to the NavHost
val saveDialogState = remember { mutableStateOf(true) }
Button(onClick = {
navController.navigate("detail_dialog")
}, modifier = Modifier.testTag(PLACE_TAG)) {
Text(text = "helllow")
}
}
dialog("detail_dialog") {
// This content will be automatically added to a Dialog() composable
// and appear above the HomeScreen or other composable destinations
Dialog(onDismissRequest = {navController.navigate("home")}) {
Card(
shape = RoundedCornerShape(10.dp),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
// .padding(horizontal = 16.dp)
.padding(vertical = 8.dp),
elevation = 8.dp
){
Text(text = "helllow", modifier = Modifier.testTag(BUTTON_TAG))
}
}
}
}
}
}
As #DanielO said you can use the isRoot() selector, see below. That however prints out the same message as before.
A possible workaround is to instead print both root trees using something like
composeTestRule.onAllNodes(isRoot()).printToLog("currentLabelExists")
You have to distinctivly select which root you are looking for. By using the selectors:
.get( index )
.onFirst()
.onLast()
When added it should look like this:
composeTestRule.onAllNodes(isRoot()).get(1).printToLog("T:")
composeTestRule.onAllNodes(isRoot()).onFirst().printToLog("T:")
composeTestRule.onAllNodes(isRoot()).onLast().printToLog("T:")
I'm just learning how to use LayzyColumn. The LazyColumn does not show me the list of items. When I click the button, the items that are loaded in the list are not displayed.
Here my code:
#Composable
fun MainContent() {
val list = remember { mutableListOf<String>() }
LazyColumn(
contentPadding = PaddingValues(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
itemsIndexed(list) { index, item ->
Card(
backgroundColor = Color(0xFFF7C2D4),
elevation = 4.dp
) {
Row(
Modifier
.fillMaxWidth()
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = item.takeLast(5), Modifier.weight(1F))
}
}
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
Alignment.BottomEnd
) {
FloatingActionButton(onClick = { list.add(UUID.randomUUID().toString()) }) {
Icon(imageVector = Icons.Default.Add, contentDescription = "")
}
}
}
Compose cannot track changes of plain kotlin types. You need to use Compose mutable states.
In this case mutableStateListOf should be used instead of mutableListOf.
I suggest you start with this youtube video which explains the basic principles of why do you need to use state in Compose. You can continue deepening your knowledge with state in Compose documentation.
Why my LazyColumn items are being stretched?
class RecipeListFragment: Fragment() {
private val viewModel: RecipeListViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
val recipes = viewModel.recipes.value
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "RecipeList",
style = TextStyle(
fontSize = 21.sp
)
)
Spacer(modifier = Modifier.padding(10.dp))
Button(
onClick = {
findNavController().navigate(R.id.viewRecipe)
}
) {
Text(text = "TO RECIPE FRAGMENT")
}
Spacer(modifier = Modifier.padding(10.dp))
LazyColumn{
items(recipes) { recipe ->
// RecipeCard(recipe = recipe, onClick = {})
Text(
text = recipe.title ?: "None",
style = MaterialTheme.typography.h5
)
}
}
}
}
}
}
}
android 12 preview versions prior to ~august build have this problem.
More info can be found here: https://issuetracker.google.com/issues/208694349
Try on the stable android12 and/or on the real device
The following is my code snippet. I pass in editClick that adds a data class object into chargingViewModel.contractSelfPay, which is observed as itemList state. When I click the icon, I can tell itemList state receives update by having more edit icons that are spaced evenly. However, BasicGrid Row's height is not stretched with Intrinsic.Min.
If I remove IntrinsicSize.Min, even though row's height is stretched, dividers no longer can fillMaxHeight as well as icon columns. without Intrinsic.Min
#Composable
fun ContractSelfPay(chargingViewModel: ChargingViewModel, editClick: () -> Unit = {}) {
val itemList by chargingViewModel.contractSelfPay.observeAsState()
val composeList: List<#Composable () -> Unit> = itemList?.map {
#Composable {
Row {
TempFunc { StyledText(text = it.itemTitle) }
TempFunc { StyledText(text = it.originalPrice.toString()) }
TempFunc { StyledText(text = it.selfPay.toString(), color = self_pay_blue) }
TempFunc { StyledText(text = it.count.toString()) }
TempFunc { StyledText(text = (it.selfPay * it.count).toString()) }
}
}
} ?: listOf()
val total = itemList?.map { (it.selfPay.toInt() * it.count.toInt()) }?.sum() ?: 0
BasicGrid("全自費", composeList, total = total.toString(), editClick = editClick)
}
#Composable
fun BasicGrid(
gridTitle: String,
itemList: List<#Composable () -> Unit>,
total: String = "0",
editClick: () -> Unit = {}
) {
Row(modifier = Modifier.height(IntrinsicSize.Min), verticalAlignment = Alignment.CenterVertically) {
StyledTextBold(text = gridTitle, modifier = Modifier.weight(15f).wrapContentWidth())
VerticalDivider()
Column(
modifier = Modifier.weight(60f)
) {
itemList.forEachIndexed { index, compose ->
compose()
if (index != itemList.size - 1)
HorizontalDivider()
}
if (itemList.isEmpty())
StyledText(text = "尚未有任何紀錄", modifier = Modifier.weight(1f).wrapContentSize())
}
VerticalDivider()
StyledTextBold(text = total, modifier = Modifier.weight(15f).wrapContentWidth())
VerticalDivider()
Column(
modifier = Modifier
.weight(10f)
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceEvenly
) {
itemList.forEachIndexed { index, detail ->
Image(
painter = painterResource(R.drawable.icon_mode_edit),
contentDescription = "",
modifier = Modifier
.align(Alignment.CenterHorizontally)
.clickable { editClick() },
)
if (itemList.isNotEmpty() && index != itemList.size - 1)
HorizontalDivider()
}
}
}
}
I have created issue here https://issuetracker.google.com/issues/217910352. Hopefully it gets solved.
One of the work-arounds I could think of is keeping track of height and removing IntrinsicSize.Min.
As in:
// _key_ is something that causes change of the height of the row
var height by remember(_key_) { mutableStateOf(0) }
Row(Modifier.onSizeChanged { height = it.height }) {
VerticalDivider(Modifier.height(height))
}
In your case I suppose key would be size of itemList.
Thank you Majkeee. It's been a while. The way I fixed it at the time was with custom layout modifier. Not sure if it still works today though.
fun Modifier.expandHeight() = this.then(layout { measurable, constraints ->
val placeable =
measurable.measure(constraints.copy(maxHeight = Constraints.Infinity))
layout(placeable.width, placeable.height) {
placeable.placeRelative(0, 0)
}
})
and to use it you can do
Column(modifier = Modifier.expandHeight())