Hidden bottom item in LazyColumn - Jetpack Compose - android

I am trying to create a list of items with a hidden button at the bottom. By default the button is not visible on the screen.
If a user scrolls to the bottom of the list the button should appear like it is the last item of the list.
I created illustrations to better visualize the desired behaviour:
Sketch 1: List with a few items
Sketch 2: List with a lot of items
I already tried the solution for a similar problem (https://stackoverflow.com/a/69196765/11720296) and added extra offset but unfortunately it didn't work.
Does somebody have an idea how to create this behaviour?

itemsIndexed will help in this case in following example I have used itemsIndexed in Lazycolumn it gives index which is visible to the user.
In this example I was trying to show some specific text only when first message is visible.
LazyColumn() {
itemsIndexed(tempListOfMessages) { index, localMessage ->
if (localMessage != null) {
SingleMessageView(
localMessageInfo = localMessage,
(index == 0)
)
}
}
}
when scroll that text scroll with first item.

Try this.
Scaffold { paddingValues ->
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = paddingValues
) {
...
}
}

Related

Radio button not showing correctly in jetpack compose

I created a component selectableListItem() that has a title, subtitle, and radio button icon but it shows differently on different android devices. On the emulator, it shows fine...on a real device, no radio button is showing on second item and the first item radio button is small. On another real device... the radio button on second item is very small while others are fine.
screenshoot another screenshot
Column {
FiveVerticalSpacer()
valuePoll.forEachIndexed { index, saveCustomerRequest ->
SelectionListItem(
index = index,
isSelected = saveCustomerRequest.title == onItemSelected.title,
title = saveCustomerRequest.title,
subTitle = saveCustomerRequest.description,
onClick = {
onItemSelected = saveCustomerRequest(
saveCustomerRequest.title,
saveCustomerRequest.description
)
}
)

jetpack compose Image on entire screen

I have a simple screen implemented with Jetpack Compose,
here is a preview of the screen.
There is a button like the sun on the TopAppBar which the user clicks to take a screenshot.
The problem is that I want to show the screenshot of the entire screen but without showing the status bar and the navigation bar.
Is there a solution to do this?
The composables are tied to a View which you can access with LocalView.current and through that View you can retrieve its .context and through that you can get to its Activity and to the Window object.
Once you have a reference to the Window (and to the View, if you have to support API level lower than 30), you can control status bar and navigation bar visibility.
A code example:
#Composable
fun MyFullScreenComposable() {
val view = LocalView.current
SideEffect {
requestFullScreen(view)
}
Box {
// ... other content
Button(
onClick = { requestFullScreen(view) }
) {
Text("Go fullscreen")
}
}
}
fun requestFullScreen(view: View) {
// !! should be safe here since the view is part of an Activity
val window = view.context.getActivity()!!.window
WindowCompat.getInsetsController(window, view).hide(
WindowInsetsCompat.Type.statusBars() or
WindowInsetsCompat.Type.navigationBars()
)
}
fun Context.getActivity(): Activity? = when (this) {
is Activity -> this
// this recursion should be okay since we call getActivity on a view context
// that should have an Activity as its baseContext at some point
is ContextWrapper -> baseContext.getActivity()
else -> null
}
In your case you might have to hide your action/title bar as well (or maybe you are already doing that).
Note that when the user taps on the screen while in full-screen mode, the bars will slide back. That's why I added a button as an example how you can let the user go back into full-screen mode through an action. In your case that could be a FloatingActionButton or some action on a semi-transparent top action bar.

First visible item in recycler view chagnes rest of the list

I have list of users with circle foreground on their avatar. If user is online circle is green, otherwise it is red. The problem is, whole list is red (for example) until I scroll under the user which is supposed to be green.
After that when I scroll back upwards whole list has green circles until I reach offline user which will change whole list back to red.
My bind function looks like this:
fun bind(userInfo: UserInfo) {
val foreground = ContextCompat.getDrawable(itemView.context, R.drawable.ic_online)
foreground?.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(
itemView.context, when {
userInfo.status == Status.OFFLINE -> R.color.offline_red
else -> R.color.colorAccent
}), PorterDuff.Mode.SRC_ATOP)
itemView.profilePictureImageView.foreground = foreground
val options = RequestOptions()
options.placeholder(R.drawable.ic_default_avatar)
options.circleCrop()
Glide.with(itemView.context)
.load("http://scdb.abradio.cz/uploads/interprets/r/radek-rettegy.jpg")
.apply(options)
.into(itemView.profilePictureImageView)
}
You need to call mutate on the drawable otherwise you're changing the shared instance:
val foreground = ContextCompat.getDrawable(itemView.context, R.drawable.ic_online)
.mutate()

how to set visibility GONE like android in IOS?

Anybody know a simple way to hide a label and let the other views of the screen use the place left blank ? And make the opposite when showing back that view. Something like Android setVisibility = GONE for layers.
As far as I know, using setHidden=true only hide the view from the screen but does not rearrange anything around it.
Thank you
The only way to achieve Androids .GONE functionality on iOS is to use a UIStackView
via Apples documentation
Dynamically Changing the Stack View’s Content The stack view
automatically updates its layout whenever views are added, removed or
inserted into the arrangedSubviews array, or whenever one of the
arranged subviews’s hidden property changes.
SWIFT 3:
// Appears to remove the first arranged view from the stack.
// The view is still inside the stack, it's just no longer visible, and no longer contributes to the layout.
let firstView = stackView.arrangedSubviews[0]
firstView.hidden = true
SWIFT 4:
let firstView = stackView.arrangedSubviews[0]
firstView.isHidden = true
You can achieve this easily using AutoLayout constraints.
Suppose you have three views like this:
+-----+
| A |
+-----+
+-----+
| B |
+-----+
+-----+
| C |
+-----+
and you want to make view B disappear in some cases.
Set up constraints as follows (these are just example values):
B top space to A: 4
C top space to B: 4
B height: 20
Then create an NSLayoutConstraint outlet in your code for B's height. Do this by dragging and dropping the constraint in IB.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *bHeight;
Finally, to make the view disappear, just do the following:
self.bHeight = 0;
Note that if you are doing this for a tableview cell, you may have cases where you want B to appear in some cells, but not in others.
In this case, you will have to reset the height to its "normal" value for those cells where you want it to be visible.
self.bHeight = 24;
I was looking for simple solution and found it. I don't have to use UIStackView or create outlet for constraint. Just use this:
class GoneConstraint {
private var constraint: NSLayoutConstraint
private let prevConstant: CGFloat
init(constraint: NSLayoutConstraint) {
self.constraint = constraint
self.prevConstant = constraint.constant
}
func revert() {
self.constraint.constant = self.prevConstant
}
}
fileprivate struct AssociatedKeys {
static var widthGoneConstraint: UInt8 = 0
static var heightGoneConstraint: UInt8 = 0
}
#IBDesignable
extension UIView {
#IBInspectable
var gone: Bool {
get {
return !self.isHidden
}
set {
update(gone: newValue)
}
}
weak var widthConstraint: GoneConstraint? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.heightGoneConstraint) as? GoneConstraint
}
set(newValue) {
objc_setAssociatedObject(self, &AssociatedKeys.widthGoneConstraint, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
weak var heightConstraint: GoneConstraint? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.heightGoneConstraint) as? GoneConstraint
}
set(newValue) {
objc_setAssociatedObject(self, &AssociatedKeys.heightGoneConstraint, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
private func update(gone: Bool) {
isHidden = gone
if gone {
for constr in self.constraints {
if constr.firstAttribute == NSLayoutAttribute.width {
self.widthConstraint = GoneConstraint(constraint: constr)
}
if constr.firstAttribute == NSLayoutAttribute.height {
self.heightConstraint = GoneConstraint(constraint: constr)
}
constr.constant = 0
}
} else {
widthConstraint?.revert()
heightConstraint?.revert()
}
}
}
Now, you can call view.gone = true and that's it.
You can use UIStackView if youe app supports ios 9 and above.
but if your app support ios 8 also than You have to achive it using Autolayout and add Height Constrain for View
So if you want hide than just set height constrain value 0.

Unable to change backgroundColor of a label inside a TableViewRow onClick (android) - appcelerator titanium

I am trying to update the background color of a Label inside a TableViewRow. I am using a View/Controller for the rows, creating them in code and appending them as an array to the TableView. Using onClick of the TableViewRow and Label.setBackgroundColor() inside the TableViewRow controller.
ExampleRow.xml
<TableViewRow id="exampleRow" class="exampleClass" onClick="exampleClick">
<Label id="exampleLabel" text="test" />
</TableViewRow>
ExampleRow.js
var test = 1;
function exampleClick(e) {
if(test == 1) {
$.exampleLabel.setBackgroundColor('#0f0');
test = 0;
} else {
$.exampleLabel.setBackgroundColor('#fff');
test = 1;
}
}
ExamplePage.xml
<TableView id="exampleTable" />
ExamplePage.js
var tableViewRows = [];
for(var i = 0; i < 5; i++) {
tableViewRows.push(
Alloy.createController('exampleRow', {}).getView()
);
}
$.exampleTable.setData(tableViewRows);
The problem is this does not work on the first page as soon as the app loads. If I scroll the TableViewRows outside of the screen and back in, the background color change works. If an alert box is popped up the background change works. But after first app load, the background color will not change. It also works if we use appendRow for each row, but this is substantially slower.
appendRow fix example:
for(var i = 0; i < 5; i++) {
$.exampleTable.appendRow(
Alloy.createController('exampleRow', {}).getView()
);
}
appending the rows individually sometimes fixes the bug (not every row), but for our list takes 5-8 seconds to display the table, rather than <1second using setData*
Example of the real app not working:
Example of the real app working:
This occurs after having an alert box displayed or scrolling the rows out and back in to the screen, or using appendRow for each row
Methods I have attempted to fix (did not fix):
using animations
removing the label then recreating and adding a new label in code
removing class from the TableViewRow
I am using Titanium SDK 5.0.2.GA and compiling on android 5.1.1.
Try to use click event of tableView instead of tableViewRow :
<TableView onClick="yourTableViewClickEvent"></TableView>
and then define what logic will be executed inside this function callback :
function yourTableViewClickEvent(e){
// access selected row
var currentSelectedRow = e.row;
// current selected Label we assume here that the row contain a label as first child (exactly what you have in your row definition
var currentLabel = currentSelectedRow.children[0]
// change label background color
currentSelectedRow.backgroundColor = "#0f0"
// You can even (i know it is no good to do that :)) test if the color is white or #0f0 like so
if(currentSelectedRow.backgroundColor == "#fff")
currentSelectedRow.backgroundColor = "#0f0"
else
currentSelectedRow.backgroundColor = "#fff"
}

Categories

Resources