JetPack Compose onClick function - kotlin

Please try to tolerate my inexperience.
I'm practicing Jetpack Compose navigation. I making an app that displays a set of card in a LazyHorizontalGrid format, and when clicked it navigates to a screen (destination) containing details of the card, depending on which card is clicked.
Here's what I mean:
I want to navigate to a screen (destination) that describe a particular "Favorite Collections" when clicked, depending on which is clicked.
I was following a tutorial on youtube, but I got lost when he was using Companion Object on a new activity (i.e having multiple activity in a single project and navigating by intent), since that's not recommended I'm not doing that, so I don't know where to put my Companion Object.
RecyclerView in Jetpack Compose - Jetpack Compose For Beginners #7
As I get errors when I try to put the Companion Object in the file of the Screen I'm trying to navigate to, error; Modifier 'companion' is not applicable inside 'file', or In a Composable in the file, then I get this error; Unresolved reference: companion.
This is the screen I'm trying to navigate to (let's call it; DetailScreen);
#Composable
fun DisplayHomeInfo(){
WelcomeText()
HomeInfoDetails(homeInfo = )
}
#Composable
fun WelcomeText() {
Text(
text = "Welcome, to Home Information",
style = MaterialTheme.typography.h3,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 18.dp)
)
}
#Composable
fun HomeInfoDetails(homeInfo: HomeInfo) {
Card(
modifier = Modifier
.padding(10.dp)
.clip(CircleShape),
elevation = 10.dp,
) {
....
This is the screen I'm trying to navigate from;
#Composable
fun HomeScreen(onHomeCardClick: () -> Unit) {
HomeContentScreen(onHomeCardClick = onHomeCardClick)
}
....
Data class I want to load on the detail screen;
data class HomeInfo(
val id: Int,
val title: String,
val sex: String,
val age: Int,
val description: String,
val homeInfoImageId: Int = 0
)
And this is the Object I want to match with the data;
object HomeInfoModel {
val homeInfoModelList = listOf(
HomeInfo(
id = 1,
title = "Monty",
sex = "Male",
age = 14,
description = "Monty enjoys chicken treats and cuddling while watching Seinfeld.",
homeInfoImageId = R.drawable.ab1_inversions
),
...
)
}
To summarize everything, MY QUESTION is how do I pass the data to the detailScreen, and show each card details, depending on the card clicked.
Please I understand my explanation is not very clear, and I'll be more than happy to clarify anything.
No information is too small, I will appreciate any help. Thanks a lot in advance.

Related

Composable Focus

I have a project where we display a graph, this graph is in an Box which is scrollable.
By opening the view, we need to center the root node which causes the problem currently.
Determining the position and setting the values of the states is currently done the following way:
.onGloballyPositioned { coordinates -> scrollBy = coordinates.positionInParent().y - dpstate!!.scrollState.firstVisibleItemScrollOffset
}
.onFocusChanged {
if(it.isFocused ){
print("is focused")
scope.launch { dpstate!!.scrollState.animateScrollBy(scrollBy)
dpstate!!.offsetState.value = Offset(leftX.toFloat(),dpstate!!.offsetState.value.y)
}
}
}
in the modifier of the box.
The state dpstate is an instance of the following:
data class DisplayState(
val scrollState: LazyListState,
val scaleState: MutableState<Float>,
val offsetState: MutableState<Offset>,
val editState: MutableState<Boolean>,
val showInfo:Map<Int, MutableState<Boolean>>,)
Important is, that I need to center by opening it, not by clicking a button.
My try was in the calling code of all of this the following code:
DisposableEffect(Unit){
com.github.tukcps.appel.ui.rendering.focusRequester!!.requestFocus()
onDispose { }
}
There is no exception, it just don't do anything, thanks for your help.

Jettpack Compose not showing Ads banner (AdView)

I'm using the code below to display AdMob Ads, but unfortunately it's not showing anything. Please let me know if I have missed something
#Composable
fun AdvertView(modifier: Modifier = Modifier) {
AndroidView(
modifier = modifier.fillMaxWidth(),
factory = { context ->
AdView(context).apply {
adSize = AdSize.BANNER
adUnitId = "ca-app-pub-3940256099942544/6300978111"
loadAd(AdRequest.Builder().build())
}
},
update = {
it.apply {
loadAd(AdRequest.Builder().build())
}
}
)
}
I got a similar problelm.. What worked for me was making sure I had internet connection and waiting a bit for the banner ad to load when I run my code..
Also Since Admob 21.0.0, you would get the following error:
Val cannot be reassigned
So, instead of
adSize = AdSize.BANNER
use
setAdSize(AdSize.BANNER)
AdMob in Jetpack Compose (Banner and Interstitial) enter link description here

Swipe to Recycler View Item until displayed

I have a nested Recycler lists which don't have ~~scrolling~~ & nestedScrollingEnabled=false. I'm attempting to swipe up and click on the recycler item by it's text. Having issues with determining when to swipe and how far.
UPDATE: This may have scrolling, I may need to specify the ViewHolder of the Item with text instead of the view with text... Experimenting...
parent_recycler_list
recycler_list
List item A
List item B
recycler_list
List item A
List item B
So far I am able to find the item and try to click on it:
Espresso.onView(
CoreMatchers.allOf(
ViewMatchers.withId(R.id.recycler_list),
ViewMatchers.hasDescendant(recyclerViewItemWithText(text))
)
).perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
recyclerViewItemWithText(text),
ViewActions.click()
)
)
fun recyclerViewItemWithText(text: String) = object : BoundedMatcher<View, View>(View::class.java) {
override fun describeTo(description: Description?) {
description?.appendText("Searching for text with: $text")
}
override fun matchesSafely(item: View?): Boolean {
val views = ArrayList<View>()
item?.findViewsWithText(views, text, View.FIND_VIEWS_WITH_TEXT)
return when (views.size) {
1 -> true
else -> false
}
}
}
This only works by it self when the list item is displayed.
I have tried to swipe until the view item is displayed:
Espresso.onView(ViewMatchers.withId(R.id.parent_recycler_list)).perform(
ViewActions.repeatedlyUntil(
ViewActions.swipeUp(),
Matchers.allOf(
ViewMatchers.hasDescendant(ViewMatchers.withText(text)),
isCompletelyDisplayed()
), 10
)
)
This will always swipe at least once... and can swipe past the view item I'm looking for.
Is there a way I can be more precise in when and how far to swipe?
I'm a bit of a novice still and don't know much about custom swipe actions on view holders. Thanks
When trying to use nestedScrollTo()
java.lang.RuntimeException: Action will not be performed because the
target view does not match one or more of the following constraints:
(view has effective visibility=VISIBLE and is descendant of a: (is
assignable from class: class androidx.core.widget.NestedScrollView))
You can simply use ViewActions.scrollTo() if your nested recycler views do not have nested scrolling enabled, but you'll need to tweak the action first because it does not support NestedScrollView:
fun nestedScrollTo(): ViewAction = object : ViewAction {
private val scrollTo = ViewActions.scrollTo()
override fun getConstraints(): Matcher<View> {
return Matchers.allOf(
ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
ViewMatchers.isDescendantOfA(Matchers.anyOf(ViewMatchers.isAssignableFrom(NestedScrollView::class.java))))
}
override fun getDescription(): String = scrollTo.description
override fun perform(uiController: UiController, view: View) = scrollTo.perform(uiController, view)
}
Then use the new custom action to scroll, for example:
onView(withText("query")).perform(nestedScrollTo(), click())
Avoid using swipe in this use case if possible, they can be unreliable at times.
6 months later I figured out a bit more about Recycler lists and that I was trying to use them wrong, or at least figured out which Recycler actions work (some don't seem to work at all). This had nothing to do with Nested scrolling even though I have nested recycler lists.
Needed to use a swipe up action as a back up for when the list doesn't exist in the hierarchy.
Also there is a Potential infinite loop.
fun tapRecyclerItem(titleText: String) {
val parentList by lazy { onView(withId(R.id.parent_recycler_list)) }
try {
//Try to scroll to the item in the child list
onView(allOf(
withId(R.id.recycler_list),
hasDescendantWithText(titleText)
)).perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
hasDescendantWithText(titleText),
ViewActions.scrollTo()
)
)
// Tap the title
onView(allOf(withId(R.id.title), withText(titleText))).tap()
} catch (ex: NoMatchingViewException) {
// Swipe up and try again
parentList.perform(swipeCenterUp())
tapRecyclerItem(titleText)
}
}
fun hasDescendantWithText(text: String): Matcher<View> {
return Matchers.allOf(
hasDescendant(withText(text)),
withEffectiveVisibility(VISIBLE)
)
}
fun swipeCenterUp(): ViewAction? {
return ViewActions.actionWithAssertions(
GeneralSwipeAction(
Swipe.FAST,
GeneralLocation.CENTER,
GeneralLocation.TOP_CENTER,
Press.FINGER
)
)
}

Android Jetpack Compose NumberPicker Widget Equivalent

What is the recommended solution for creating a NumberPicker Widget in Jetpack Compose? Similar to the image below. I am able to create an NumberPicker using an AndroidView within my composable but the view does not seem to allow flings or snap to position. Btw the UI below shows three NumberPickers placed in a row. It is not supposed to represent a DatePicker
By coincidence I've implemented a screen like that last week.
I can't share the whole code here, but basically what I did was:
Create a layout with a DatePicker (res/layout/date_picker.xml).
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/datePicker"
android:theme="#style/DatePickerStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner" />
Then, use it in your composable function.
#Composable
fun DatePicker(
onDateSelected: (Date) -> Unit
) {
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { context ->
val view = LayoutInflater.from(context).inflate(R.layout.date_picker, null)
val datePicker = view.findViewById<DatePicker>(R.id.datePicker)
val calendar = Calendar.getInstance() // show today by default
datePicker.init(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
) { _, year, monthOfYear, dayOfMonth ->
val date = Calendar.getInstance().apply {
set(year, monthOfYear, dayOfMonth)
}.time
onSelectedDateUpdate(date)
}
datePicker
}
)
}
Finally, use it in a ModalBottomSheetLayout
Editing my answer... Using a NumberPicker working as well...
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { context ->
NumberPicker(context).apply {
setOnValueChangedListener { numberPicker, i, i2 -> }
minValue = 0
maxValue = 50
}
}
)
Here is the result.
I know maybe you are not looking for something like this. But since there is no such widget in compose yet and compose is all about making your way easier to build your own component. So Apart from android.widget NumberPicker, you can make something like this one. You can change the visualization more like the NumberPicker widget and add your callback and stuff.
Have you checked this one on github? ComposeNumberPicker.Kt
We are using this library in our compose project for number picker widget.
https://github.com/ChargeMap/Compose-NumberPicker

How to create a paint application like Messenger's emoji paint on captured photo in Kotlin

So I'm making an app which needs to paint garland, light bulbs and other decoration. I have a code which will make an imageview on Action_Move but the app crashes. see the code below
fun drawLights(){
val listener = View.OnTouchListener(function = { view, motionEvent ->
val x = motionEvent.getX()
val y = motionEvent.getY()
when (motionEvent.action){
MotionEvent.ACTION_DOWN -> {
Toast.makeText(this,"Action Down",Toast.LENGTH_SHORT).show()
}
MotionEvent.ACTION_MOVE -> {
Toast.makeText(this, "Moving", Toast.LENGTH_SHORT).show()
////Imageview Creation Here using late init var
}
MotionEvent.ACTION_UP -> {
Toast.makeText(this,"Done" ,Toast.LENGTH_SHORT).show()
}
}
true
})
edit_Canvas.setOnTouchListener(listener)
}
Does anyone here know any blog related to this or already resolved this problem? Thanks!
You need to look for topics on drawing on the Android Canvas. There are lots of sample codes out there
This one's from the official documentation in drawing on the Canvas https://developer.android.com/training/custom-views/custom-drawing