RecyclerView optimization issues - android

I've noticed some RV performance issues.
I have a RecyclerView with some amount of items. When I launch my Fragment with RV and trying to scroll it for the first time I see some lags. I'll attach a GIF with active GPU profiling at the end of this question.
As you can see, I have a huge FPS drop when I start scrolling then it becomes smooth. So my question is -
Is it possible to optimise this process? I tried the following:
1. To create View for all my ViewHolders once:
private var itemView: View? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (itemView == null) {
itemView = LayoutInflater.from(parent.context).inflate(R.layout.rv_contact_item, parent, false)
}
return ContactViewHolder(itemView)
}
But it's not possible, cuz this view will be attached to it's parent with first onCreateViewHolder call and I'm getting crash "Detach your view from parent first".
2. Create ViewHolders in background thread.
Doesn't do anything too.
I know there's a possibility to create View programmatically, but will it work as intended? I have a pretty difficult View, so it would take some time to try it.
UPD:
My XML for single item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_contact"
android:orientation="horizontal"
android:padding="16dp"
android:background="?attr/selectableItemBackground">
<com.myapp.custom.AvatarView
android:id="#+id/v_avatar"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginEnd="16dp"
android:layout_gravity="center"
android:transitionName="chat_avatar_transition"
tools:background="#color/pale_red">
<com.myapp.custom.UserStatusView
android:id="#+id/v_user_status"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="bottom|end"/>
</com.myapp.custom.AvatarView>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_marginEnd="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/iv_conference"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAlignBottom="true"
android:layout_marginEnd="2dp"
app:srcCompat="#drawable/ic_vector_conference"/>
<TextView
android:id="#+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:ellipsize="end"
android:lines="1"
android:transitionName="chat_name_transition"
tools:text="Title" />
</LinearLayout>
<TextView
android:id="#+id/tv_contact_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/text_light"
android:textSize="14sp"
android:ellipsize="end"
android:lines="1"
tools:text="Subtitle" />
<LinearLayout
android:id="#+id/ll_last_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/iv_message_direction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="3dp"
app:srcCompat="#drawable/ic_vector_arrow_right" />
<TextView
android:id="#+id/tv_last_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#color/text_light"
android:textSize="14sp"
android:ellipsize="end"
android:lines="1"
tools:text="Hello!" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/iv_birthday"
android:layout_width="24dp"
android:layout_height="24dp"
app:srcCompat="#drawable/ic_vector_birthday" />
<ImageView
android:id="#+id/iv_app_type"
android:layout_width="24dp"
android:layout_height="24dp"
app:srcCompat="#drawable/ic_vector_mobile" />
<ImageView
android:id="#+id/iv_important_messages"
android:layout_width="24dp"
android:layout_height="24dp"
app:srcCompat="#drawable/ic_vector_flag" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_message_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="bottom|end"
app:srcCompat="#drawable/ic_vector_checked" />
<TextView
android:id="#+id/tv_unread_counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="24dp"
android:minWidth="24dp"
android:padding="3dp"
android:background="#drawable/shape_rect_rounded_12dp_blue_regular"
android:gravity="center"
android:textColor="#android:color/white"
android:layout_gravity="bottom|end"
tools:text="10" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
UPD2:
My bind() method:
fun bind(contact: ContactModel) {
avatarView.apply {
initialize(
contact.id,
contact.avatar,
contact.fullName)
}
ivConference.visibility = if (ContactType.CONFERENCE == contact.type)
View.VISIBLE
else
View.GONE
tvName.text = contact.fullName
tvContactSubtitle.text = contact.subtitle
contact.lastMessageDirection?.let { direction ->
llLastMessage.visible
ivLastMessageDirection.setImageDrawable(
VectorDrawableCompat.create(
itemView.context.resources,
direction.icon,
null)
)
tvLastMessage.text = contact.lastMessage
} ?: llLastMessage.invisible
ivBirthday.visibility = if (contact.isBirthdayInc) {
View.VISIBLE
} else
View.GONE
ivImportantMessages.visibility = if (contact.hasImportantMessages)
View.VISIBLE
else
View.GONE
if (contact.unreadCounter == 0) {
tvUnreadCounter.gone
} else {
tvUnreadCounter.visible
tvUnreadCounter.text = contact.unreadCounter.toString()
}
}

That is because the quality of the image you've used is too high for so many item which takes time to optimize.
Please convert your images to WebP format for better performance.
Hope it helps.

Related

RecyclerView lags while Scrolling

I have a recyclerView that loads songs from memory and when I scroll it lags,
This is my ViewBinding.
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.titleView.text = musicList[position].title
holder.albumName.text = musicList[position].artist
holder.duration.text = formatDuration(musicList[position].length)
Glide
.with(context)
.load(musicList[position].artUri)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.apply(RequestOptions().placeholder(R.drawable.image_as_cover).centerCrop())
.into(holder.imageView)
holder.itemView.setOnClickListener {
if (MainActivity.isSearching)
sendIntent(position = position, parameter = "MusicAdapterSearch")
else
sendIntent(position = position, parameter = "MusicAdapter")
}
}
I noticed that when I removed image loading from binding i.e Glide, I did not lag, and it only first scrolled each time I open the app.
How can I Handle the lag, is there any other library I should use or any caching-like thing?
Here is my XML.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:theme="#style/Theme.Music.Font">
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_margin="5dp"
android:contentDescription="#string/cover"
android:src="#drawable/image_as_cover"
app:shapeAppearance="#style/roundedImageView" />
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="#+id/duration"
android:layout_toEndOf="#+id/imageView"
android:orientation="vertical">
<TextView
android:id="#+id/titleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:fontFamily="#font/medium"
android:maxLines="1"
android:singleLine="true"
android:text="#string/love_is_gone_by_slander_forever_on_love"
android:textSize="15sp" />
<TextView
android:id="#+id/albumName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:fontFamily="#font/medium"
android:maxLines="1"
android:text="#string/albumName"
android:textSize="12sp"
android:theme="#style/Theme.Music.FontColor" />
</LinearLayout>
<TextView
android:id="#+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:fontFamily="#font/medium"
android:maxLines="1"
android:text="#string/duration"
android:textSize="11sp" />
</RelativeLayout>
It is maybe due to high-quality images with glide
Try to resize it by adding request option with center crop
RequestOptions myOptions = new RequestOptions()
.centerCrop() // or centerCrop
.override(800, 500);//your imageview frame size
Glide.with(activity)
.applyDefaultRequestOptions(myOptions)
.load(list.get(position).appthumbnail)
.error(R.drawable.no_image_available)
.into(holder.ivImage);
hope it will help you
The reason I asked for the view holder layout because it might be one of the reason resulting jank.
You may give a try using below XML to see whether the issue will be resolved.
(by replacing the relative layout and child linear layout to constraint layout)
e.g., view holder xml example
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:theme="#style/Theme.Music.Font">
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_margin="5dp"
android:contentDescription="#string/cover"
android:src="#drawable/image_as_cover"
app:shapeAppearance="#style/roundedImageView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="#+id/linearLayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#id/imageView"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="#+id/titleView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:maxLines="1"
android:singleLine="true"
android:fontFamily="#font/medium"
android:text="#string/love_is_gone_by_slander_forever_on_love"
android:textSize="15sp"
android:text="123"
app:layout_constraintTop_toTopOf="#id/linearLayout"
app:layout_constraintBottom_toTopOf="#id/albumName"
app:layout_constraintStart_toStartOf="#id/linearLayout"
app:layout_constraintEnd_toEndOf="#id/linearLayout" />
<TextView
android:id="#+id/albumName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:fontFamily="#font/medium"
android:maxLines="1"
android:singleLine="true"
android:text="#string/love_is_gone_by_slander_forever_on_love"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="#id/titleView"
app:layout_constraintBottom_toTopOf="#id/duration"
app:layout_constraintStart_toStartOf="#id/linearLayout"
app:layout_constraintEnd_toEndOf="#id/linearLayout" />
<TextView
android:id="#+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:fontFamily="#font/medium"
android:maxLines="1"
android:text="#string/duration"
android:textSize="11sp"
app:layout_constraintTop_toBottomOf="#id/albumName"
app:layout_constraintBottom_toBottomOf="#id/linearLayout"
app:layout_constraintStart_toStartOf="#id/linearLayout"
app:layout_constraintEnd_toEndOf="#id/linearLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
REF
https://developer.android.com/topic/performance/vitals/render#common-jank
"If your view types look good, look at reducing the cost of your inflation. Reducing unnecessary container and structural Views can help – consider building itemViews with ConstraintLayout, which can make it easy to reduce structural Views. If you want to really optimize for performance, your items hierarchies are simple, and you don't need complex theming and style features, consider calling the constructors yourself – note though, that it's often not worth the tradeoff of losing the simplicity and features of XML."

GridLayout RecyclerView with layout_height="wrap_content"

The items in my RecyclerView Grid are stretched automatically if the left item is shorter and the right item is taller or vice versa (2 grid spans) because I want to use layout_height="wrap_content". How to keep that left item from being stretched automatically? I still want to use the GridLayout style because in my case it is not suitable if using StaggeredGridLayout (because it is more suitable for photo galleries).
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/very_light_gray"
android:paddingBottom="61dp"
tools:context="Fragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_explore_buyer_outlet"
android:layout_width="0dp"
android:layout_height="0dp"
android:clipToPadding="false"
android:overScrollMode="ifContentScrolls"
android:paddingEnd="#dimen/_20sdp"
android:paddingBottom="28dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="2"
tools:ignore="RtlSymmetry"
tools:itemCount="18"
tools:listitem="#layout/item_grid" />
</androidx.constraintlayout.widget.ConstraintLayout
</androidx.coordinatorlayout.widget.CoordinatorLayout>
item_grid.xml
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="177dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_14sdp"
android:layout_marginTop="#dimen/_14sdp"
android:layout_marginEnd="#dimen/_minus18sdp"
android:layout_marginBottom="-7dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="14dp"
app:cardElevation="1dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_item_outlet_buyer_photo"
android:layout_width="match_parent"
android:layout_height="112dp"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
android:src="#drawable/outlet10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tv_item_outlet_buyer_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="9dp"
android:background="#drawable/outlet_buyer_status_open_label"
android:fontFamily="#font/notosansjp_medium"
android:gravity="center"
android:includeFontPadding="false"
android:paddingHorizontal="8dp"
android:paddingTop="3dp"
android:paddingBottom="3.75dp"
android:textColor="#color/white"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="#+id/iv_item_outlet_buyer_photo"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="SmallSp"
tools:text="Open" />
<TextView
android:id="#+id/tv_item_outlet_buyer_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10.5dp"
android:fontFamily="#font/notosansjp_bold"
android:includeFontPadding="false"
android:lineSpacingExtra="1.5dp"
android:paddingStart="15dp"
android:paddingEnd="#dimen/_17sdp"
android:paddingBottom="2dp"
android:textColor="#color/dark_gray"
android:textSize="#dimen/_10ssp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_item_outlet_buyer_photo"
tools:text="Guttenburg, Alazka" />
<ImageView
android:id="#+id/iv_item_outlet_buyer_dotted_line"
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_marginTop="5dp"
android:importantForAccessibility="no"
android:layerType="software"
android:paddingStart="16dp"
android:paddingEnd="15dp"
android:src="#drawable/dotted_shape"
app:layout_constraintEnd_toEndOf="#+id/tv_item_outlet_buyer_name"
app:layout_constraintStart_toStartOf="#+id/tv_item_outlet_buyer_name"
app:layout_constraintTop_toBottomOf="#+id/tv_item_outlet_buyer_name" />
<TextView
android:id="#+id/tv_item_outlet_buyer_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4.5dp"
android:layout_marginBottom="14dp"
android:fontFamily="#font/notosansjp_regular"
android:includeFontPadding="false"
android:lineSpacingExtra="1.5dp"
android:paddingHorizontal="15dp"
android:textColor="#color/dark_gray"
android:textSize="11sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_item_outlet_buyer_dotted_line"
tools:ignore="SmallSp"
tools:text="Food ∙ Drink ∙ Snack" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
I want make my GridLayout like this (edited in Figma):
But I got like this if last textView have constraintBottom_toBottomOf(parent):
And, I got like this if last textView not have constraintBottom_toBottomOf(parent):
What should I do?
You just need to make sure your TextView's layout_height is wrap_content, and give that the black background. The containing layout should be transparent, so when it resizes to fit the grid, the extra space is just "empty". The TextView shouldn't resize with it (and neither should anything else in the item's layout), so the black area stays the same - the extra height is unused.
Here's a quick example
MainFragment.kt
class MainFragment : Fragment(R.layout.fragment_main) {
lateinit var binding: FragmentMainBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// fragment_main.xml has a RecyclerView in it with "recycler" for its ID
binding = FragmentMainBinding.bind(view)
with(binding) {
recycler.layoutManager = GridLayoutManager(requireContext(), 2)
recycler.adapter = Adapterino(requireContext())
}
}
private class Adapterino(val context: Context) : RecyclerView.Adapter<Adapterino.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
ItemViewBinding.inflate(LayoutInflater.from(context)).run(::ViewHolder)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// just generating random amounts of text to get some variation
holder.binding.textView.text =
generateSequence { "cats" }.take(Random.nextInt(5, 20)).joinToString(" ")
}
override fun getItemCount(): Int = 20
private class ViewHolder(val binding: ItemViewBinding) : RecyclerView.ViewHolder(binding.root)
}
}
item_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp"
>
<View
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#color/black"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="240dp"
android:src="#mipmap/ic_launcher"
/>
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/black"
android:textColor="#color/white"
android:textSize="20sp"
/>
</LinearLayout>

How to align text of textview in RecyclerView at the bottom

I am creating a list of text sizes UI that will have the different sizes of the same text rendering in the RecyclerView.
The requirement is, the text item that is rendering in the RecyclerView shall render from the bottom of the view, but its rendering from the top. Here is my code:
RecyclerView declaration:
<RelativeLayout
android:id="#+id/sizes_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:elevation="30dp"
android:paddingVertical="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="#+id/size_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/subtitles"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:id="#+id/size_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="16dp"
android:gravity="center_vertical"
android:minWidth="50dp"
android:text="#string/size"
android:textColor="#color/white"
android:textStyle="bold"
tools:textColor="#color/black" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/text_track_size_list_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#+id/size_textview"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</RelativeLayout>
</RelativeLayout>
View Item declaration:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/focus_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp">
<TextView
android:id="#+id/row_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingHorizontal="10dp"
android:paddingVertical="7dp"
android:textAllCaps="false"
android:textColor="#drawable/text_size_color"
tools:text="Aa" />
</FrameLayout>
Bind View Holder method:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val textSizeOption: TextSizeOption = extSizeOptions[position]
holder.focusView.tag = textSizeOption
holder.rowItem.textSize = textSizeOption.fontSize
if(mSelectedFormat != null && mSelectedFormat == textSizeOption.id) {
holder.focusView.isSelected = true
} else {
holder.focusView.isSelected = (position == 0 && mSelectedFormat == null)
}
}
I have tried multiple things like wrapping the item view in the Relative Layout and giving alignParentBottom, etc but that didn't work as well.
Here is the screenshot of how it's looking right now:
Sizes text top aligning
Even the Size label is not centre aligning as it's given in the code. Not sure if I am missing something, but any help will be super appreciated
Modifying your view item like this will solve your problem
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/focus_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginHorizontal="10dp"
android:orientation="horizontal">
<TextView
android:layout_gravity="center_vertical"
android:id="#+id/row_item"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#drawable/text_size_color"
android:text="Aa" />
</LinearLayout>

Horizontal Scroll View always scrolling to end when keyboard appear

I have 3 HorizontalScrollview, for each of them i have customView contain editText that i add dynamically depend from web service response. The problem is, when i want to change value in editText and keyboard appear, the HorizontalScrollView scroll automatically to the end, so i can't properly input value to my edit text. My Question is how to prevent autoscroll in my HorizontalScrollView so i can input value on my editText? and the HorizontalScrollView only scroll when user scroll it.
I've search and my problem similar with this thread but the sugestion didn't work. here is workaround that i already try :
Add android:windowSoftInputMode="stateHidden|adjustNothing" or
android:windowSoftInputMode="stateHidden|adjustResize" already try
adjustPan and other combination but it's impact nothing.
Add android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true" in LinearLayout inside my HorizontalScrollView and it's also impact Nothing.
Add android:descendantFocusability="blocksDescendants the
HorizontalScrollView didn't scroll automatically but i can't change value on my edit text, it similar when i add android:focusable = "false" in my editText
Add code bellow but impact nothing.
scrollLayout.descendantFocusability = ViewGroup.FOCUS_BEFORE_DESCENDANTS
scrollLayout.isFocusable = true
scrollLayout.isFocusableInTouchMode = true
scrollLayout.setOnTouchListener { v, event ->
v.requestFocusFromTouch()
false}
Here is My Code
private fun setUpList(rootLayout: LinearLayout, scrollLayout: HorizontalScrollView, items: List<ProductItem>) {
//config horizontal scroll view
scrollLayout.descendantFocusability = ViewGroup.FOCUS_BEFORE_DESCENDANTS
scrollLayout.isFocusable = true
scrollLayout.isFocusableInTouchMode = true
scrollLayout.setOnTouchListener { v, event ->
v.requestFocusFromTouch()
false
}
// add customView to linear layout
rootLayout.removeAllViews()
for (item in items) {
val view = EditableThumbnailProduct(context)
view.setProductInfo(item)
view.setOnProductChangeListener(onChangeListener())
rootLayout.setBackgroundColor(Color.TRANSPARENT)
rootLayout.addView(view)
}
}
Here is my XML
<HorizontalScrollView
android:id="#+id/scrollMed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="#+id/contentMed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#android:color/transparent"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal" />
</HorizontalScrollView>
Here is my custom view
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#android:color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical">
<ImageView
android:id="#+id/img_thumbnail"
android:layout_width="150dp"
android:layout_height="120dp"
android:background="#color/gray_border"
android:scaleType="fitXY" />
<TextView
android:id="#+id/txt_product_name"
style="#style/DefaultTextTitle"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_margin="5dp"
android:ellipsize="end"
android:gravity="center"
android:maxLines="2"
android:text="#string/product_name_label" />
<TextView
android:id="#+id/txt_product_stock"
style="#style/DefaultTextSubTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:gravity="center"
android:text="#string/available_stock_label" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/gray_border" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="vertical">
<Button
android:id="#+id/btn_add_to_cart"
style="#style/WhiteTitle"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:background="#drawable/round_button_orange"
android:gravity="center"
android:text="#string/buy_button_label"
android:visibility="invisible" />
<RelativeLayout
android:id="#+id/layout_plus_minus"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:orientation="horizontal">
<ImageView
android:id="#+id/btn_minus"
style="#style/WhiteTitle"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:background="#drawable/round_button_blue"
android:paddingLeft="5dp"
android:paddingTop="11dp"
android:paddingRight="5dp"
android:paddingBottom="11dp"
android:scaleType="fitXY"
app:srcCompat="#drawable/ic_minus" />
<ImageView
android:id="#+id/btn_delete"
style="#style/WhiteTitle"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:background="#drawable/round_button_blue"
android:padding="3dp"
android:scaleType="fitXY"
android:visibility="invisible"
app:srcCompat="#drawable/ic_delete" />
<EditText
android:id="#+id/txt_cart_amount"
style="#style/LightTextTitle"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_marginLeft="40dp"
android:layout_marginRight="10dp"
android:backgroundTint="#color/blue_text_color"
android:inputType="number"
android:maxLength="3"
android:paddingBottom="5dp" />
<ImageView
android:id="#+id/btn_plus"
style="#style/WhiteTitle"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:background="#drawable/round_button_blue"
android:gravity="center"
android:padding="5dp"
android:scaleType="fitXY"
android:textSize="16sp"
app:srcCompat="#drawable/ic_plus" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
All sugestion will be appreciate. Thanks in advance.

How create customview touch the same timerpicker?

I want create a View the same Image.
Touch value on View:
I using the solution create TextView and touch on TextView:
This is layout xml: i create 6 TextViews to display value when Touch on Screen.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/txtPreSelect1"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:gravity="center"
android:text="000"
/>
<TextView
android:id="#+id/txtPreSelect2"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:gravity="center"
android:text="0"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="200dp"
android:layout_height="1dp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/txtSelect1"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:layout_marginRight="#dimen/d_40"
android:gravity="center"
android:text="001"
/>
<TextView
android:id="#+id/txtSelect2"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:gravity="center"
android:text="1"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="200dp"
android:layout_height="1dp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/txtNextSelect1"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:layout_marginRight="#dimen/d_40"
android:gravity="center"
android:text="002"
/>
<TextView
android:id="#+id/txtNextSelect2"
android:layout_width="#dimen/d_60"
android:layout_height="match_parent"
android:gravity="center"
android:text="2"
/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center|right"
android:orientation="horizontal">
<TextView
android:id="#+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:gravity="center"
android:text="#string/btnCancel"/>
<TextView
android:id="#+id/btnOK"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:text="#string/btnOK"
/>
</LinearLayout>
</LinearLayout>
and i create event Touch on TextViews, to change value of Textview:
dialog.txtPreSelect1.setOnTouchListener {v: View, event: MotionEvent ->
// Perform tasks here
when (event.action)
{
MotionEvent.ACTION_DOWN ->{
yValue=event.y
}
MotionEvent.ACTION_MOVE ->{
val curentY=event.y
if(curentY>yValue)
{
if(curentY>yValue) {
yValue=curentY
var iStartValue=dialog.txtPreSelect1.text.toString().toInt() - iStep1
dialog.txtPreSelect1.text = iStartValue.toString()
iStartValue=iStartValue +iStep1
dialog.txtSelect1.text = iStartValue.toString()
iStartValue=iStartValue +iStep1 dialog.txtNextSelect1.text = iStartValue.toString()
}
}
else if(curentY<yValue)
{
if(curentY<yValue) {
yValue=curentY
var iStartValue=dialog.txtPreSelect1.text.toString().toInt() + iStep1
dialog.txtPreSelect1.text = iStartValue.toString()
iStartValue += iStep1
dialog.txtSelect1.text = iStartValue.toString()
dialog.txtNextSelect1.text = iStartValue.toString()
}
}
}
}
true
}
How can create event move text the same image 2?
Or Exist other View can process my work?
Thank all.
If I understand correctly your problem is in creating two views with lists, so you can touch and scroll them separately.
You can try to dive into this library that is quite similar what you are trying to reach: SingleDateAndTimePicker
My best guess is you want to use native component. You can use ListView but that would require much code than Number Picker. Number Picker is specifically designed to handle such situations.
Here in SO a Nice example can show you how to use it in dialog. Basically you need a LinearLayout with Horizontal Orientation and place two Number Picker inside it.
You can set MinValue and MaxValue with the help of java/kotlin like this:
numberPicker.setMaxValue(50);
numberPicker.setMinValue(1);
let me know if you have any query.

Categories

Resources