Reputation: 359
I am trying to have a Recycler View with Cards within a bottom sheet where the user "scrolls" up to reveal all of the Cards but I am having issues in accomplishing this. How can I have it so that the Recycler View with Cards is inside the bottom sheet? Any help is appreciated-I've been at this for days and cannot figure it out. Is there a way to do what the photo is showing in Android? Attached image is something what I am trying to replicate but just cannot seem to find anything that can do this:
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (supportActionBar != null)
supportActionBar?.hide()
val modelList = readFromAsset()
val adapter = CustomAdapter(modelList, this)
rcv.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) as RecyclerView.LayoutManager?
rcv.adapter = adapter;
adapter.setOnItemClickListener(object : CustomAdapter.ClickListener {
override fun onClick(pos: Int, aView: View) {
Toast.makeText(this@MainActivity, modelList.get(pos).name, Toast.LENGTH_SHORT).show()
}
})
}
private fun readFromAsset(): List<Model> {
val modeList = mutableListOf<Model>()
val bufferReader = application.assets.open("android_version.json").bufferedReader()
val json_string = bufferReader.use {
it.readText()
}
val jsonArray = JSONArray(json_string);
for (i in 0..jsonArray.length() - 1) {
val jsonObject: JSONObject = jsonArray.getJSONObject(i)
val model = Model(jsonObject.getString("name"), jsonObject.getString("version"))
modeList.add(model)
}
return modeList
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:id="@+id/rcv"/>
CustomAdapter.kt
class CustomAdapter(val modelList: List<Model>, val context: Context) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ViewHolder).bind(modelList.get(position));
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return ViewHolder(layoutInflater.inflate(R.layout.row_item, parent, false))
}
override fun getItemCount(): Int {
return modelList.size;
}
lateinit var mClickListener: ClickListener
fun setOnItemClickListener(aClickListener: ClickListener) {
mClickListener = aClickListener
}
interface ClickListener {
fun onClick(pos: Int, aView: View)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
override fun onClick(p0: View?) {
mClickListener.onClick(adapterPosition, itemView)
}
fun bind(model: Model): Unit {
itemView.txt.text = model.name
itemView.sub_txt.text = model.version
val id = context.resources.getIdentifier(model.name.toLowerCase(), "drawable", context.packageName)
itemView.img.setBackgroundResource(id)
}
}
}
row_item
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_marginTop="10dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
card_view:cardCornerRadius="30dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="false"
card_view:contentPadding="5dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="Title"
android:textSize="20sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/img"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_marginStart="25dp"
android:layout_toRightOf="@+id/txt"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/sub_txt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="25dp"
android:layout_toRightOf="@+id/img"
android:autoSizeMaxTextSize="8sp"
android:autoSizeMinTextSize="6sp"
android:autoSizeStepGranularity="2sp"
android:autoSizeTextType="uniform"
android:text="Title"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Upvotes: 0
Views: 1502
Reputation: 2043
You need to use BottomSheet to approach this.
your BottomSheet
class will be like this.
class CustomBottomSheet : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.layout_bottomsheet)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val modelList = readFromAsset()
val adapter = CustomAdapter(modelList, this)
rcv.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) as RecyclerView.LayoutManager?
rcv.adapter = adapter;
adapter.setOnItemClickListener(object : CustomAdapter.ClickListener {
override fun onClick(pos: Int, aView: View) {
Toast.makeText(context, modelList.get(pos).name, Toast.LENGTH_SHORT).show()
}
})
}
private fun readFromAsset(): List<Model> {
val modeList = mutableListOf<Model>()
val bufferReader = context?.assets?.open("android_version.json").bufferedReader()
val json_string = bufferReader.use {
it.readText()
}
val jsonArray = JSONArray(json_string);
for (i in 0..jsonArray.length() - 1) {
val jsonObject: JSONObject = jsonArray.getJSONObject(i)
val model = Model(jsonObject.getString("name"), jsonObject.getString("version"))
modeList.add(model)
}
return modeList
}
}
layout_bottomsheet
<?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:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="10dp"
app:behavior_hideable="true"
app:behavior_peekHeight="100dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" />
</LinearLayout>
Then you need to show the bottomsheet from your activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (supportActionBar != null)
supportActionBar?.hide()
// show bottom sheet
val bottomSheetDialogFragment: BottomSheetDialogFragment = CustomBottomSheet()
bottomSheetDialogFragment.show(
supportFragmentManager, bottomSheetDialogFragment.tag
)
}
}
For more, you can read this. or you can search about Bottomsheet. I hope this helps.
Upvotes: 2
Reputation: 3602
First write a class extending BottomSheetDialogFragment class with your custom layout
class BaseBottomSheetDialogTest: BottomSheetDialogFragment(){
companion object {
fun newInstance(position: Int, callback: BaseBottomSheetDialogTestCallBack) = BaseBottomSheetDialogTest(callback).apply {
arguments = Bundle().apply {
putInt("CUSTOM_DATA", position)
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.your_custom_layout, container, false)
return view
}
}
Then call it like this
val bottomSheetDialog = BaseBottomSheetDialogTest.newInstance(0,CALL_BACK_INTERFACE_IF YOU_NEED)
bottomSheetDialog!!.show(fragmentManager, "TAG_STRING")
This example is with how to pass data and a callback method.
Upvotes: 0
Reputation: 1420
Try to use Bottom Sheet Dialog Or Bottom Sheet Dialog Fragment For Display Bottom Sheet In Adapter Class
BottomSheetDialog Example
View view =
((FragmentActivity)context).getLayoutInflater().inflate(R.layout.fragment_bottom_sheet, null);
BottomSheetDialog dialog = new BottomSheetDialog(mContext);
dialog.setContentView(view);
dialog.show();
BottomsheetDialogFragment Example : Dialog Class
public class BottomsheetDialog extends BottomSheetDialogFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragment_bottom_sheet,container,false);
return v;
}
}
Call BottomsheetDialog in your Adapter Class Like This
BottomSheetDialogFragment bottomSheetDialogFragment = new BottomsheetDialog();
bottomSheetDialogFragment.show(((FragmentActivity)mContext).getSupportFragmentManager(), bottomSheetDialogFragment.getTag());
Upvotes: 0