I have a RecyclerView with a list of names being pulled from a firebase realtime database, as well with phone numbers, emails and addresses. I have created a layout for the cards shown in RecyclerView. I want them to only display the name and image until clicked. Once clicked they expand and show the phone number, email and address. I have done all this but the final problem I am facing is with setVisibility for the RelativeLayout inside the layout.xml for RecyclerView, since it's a different xml from the one that belongs to the activity my app keeps crashing. I have tried multiple solutions for problems similar to mine but I could never find someone with the same problem that I was facing.
Now if I use this code:
mUserInfoLayout = (RelativeLayout) findViewById(R.id.user_additional_info_layout);
mUserInfoLayout.setVisibility(View.INVISIBLE);
I get this error
Attempt to invoke virtual method 'void android.widget.RelativeLayout.setVisibility(int)' on a null object reference
However If I use the code provided below nothing happens the Layout stays visible.
My MainActivity.java OnCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
//Firebase
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
mUserDatabase.keepSynced(true);
//mUserSingleMainLayout = (RelativeLayout) findViewById(R.id.user_single_main_layout);
mUsersList = (RecyclerView) findViewById(R.id.users_list);
mUsersList.setHasFixedSize(true);
mUsersList.setLayoutManager(new LinearLayoutManager(this));
View usersingleView = getLayoutInflater().inflate(R.layout.users_single_layout, null);
mUserInfoLayout = (RelativeLayout) usersingleView.findViewById(R.id.user_additional_info_layout);
mUserInfoLayout.setVisibility(View.INVISIBLE);
//Buttons
mUserAdd = (FloatingActionButton) findViewById(R.id.user_add_btn);
mUserAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent createuserIntent = new Intent(MainActivity.this, CreateUserActivity.class);
startActivity(createuserIntent);
}
});
}
My activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/user_add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
app:fabSize="normal"
app:rippleColor="#color/colorPrimary"
android:src="#drawable/ic_add_white_24dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/users_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"/>
</RelativeLayout>
My user_single_layout.xml the layout file used in RecyclerView
<?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:orientation="vertical">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/user_single_image"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:src="#drawable/account_circle" />
<TextView
android:id="#+id/user_single_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="100dp"
android:layout_marginTop="20dp"
android:text="#string/display_name_users"
android:textColor="#color/colorBlack"
android:textSize="18sp" />
<RelativeLayout
android:id="#+id/user_additional_info_layout"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/user_single_name"
android:layout_marginTop="10dp"
android:layout_alignParentStart="true"
android:layout_marginStart="100dp">
<ImageView
android:id="#+id/user_phone_image"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/user_single_phone"
android:src="#drawable/ic_phone_black_24dp"/>
<ImageView
android:id="#+id/user_email_image"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/user_single_email"
android:layout_below="#+id/user_phone_image"
android:src="#drawable/ic_email_black_24dp"/>
<ImageView
android:id="#+id/user_address_image"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/user_single_address"
android:src="#drawable/ic_map_marker_black_24dp" />
<TextView
android:id="#+id/user_single_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/user_phone_image"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:text="Phone" />
<TextView
android:id="#+id/user_single_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_below="#+id/user_single_phone"
android:layout_toRightOf="#+id/user_email_image"
android:layout_marginTop="10dp"
android:text="Email" />
<TextView
android:id="#+id/user_single_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_below="#+id/user_single_email"
android:layout_toRightOf="#id/user_address_image"
android:text="Address" />
</RelativeLayout>
</RelativeLayout>
In the user_single_layout.xml I want to make the "#+id/user_additional_info_layout" RelativeLayout invisible programatically inside MainActivity.java
Edit
My answer is focused on the Fragment lifecycle. The Activity lifecycle is different and does not contain the method I suggested.
The problem is the view that you are trying to access is null. The view is not yet inflated in the onCreate method and is therefore not yet available.
No view related logic should be executed within onCreate().
You need to use the onViewCreated() method to access your views which has the following signature:
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
}
Therefore I suggest you move all of your view related logic into this method.
First, move your code to recyclerView adapter.
Second, make relativeLayout visibility to gone and change it to linearLayout.
Third, use this code for expanding it.
private fun animateView(
view: View,
duration: Long,
initialHeight: Int,
targetHeight: Int,
onAnimationEnd: () -> Unit = {}
) {
view.apply {
val animator = ValueAnimator.ofInt(initialHeight, targetHeight)
animator.addUpdateListener {
layoutParams.height = it.animatedValue as Int
requestLayout()
if (it.animatedValue as Int > 2) {
//Make the view visible in java
//yourview.setVisibility(View.Visible)
show()
}
}
animator.addListener(object : Animator.AnimatorListener {
override fun onAnimationEnd(animation: Animator) {
layoutParams.height = targetHeight
onAnimationEnd.invoke()
}
override fun onAnimationStart(animation: Animator) {
}
override fun onAnimationCancel(animation: Animator) {}
override fun onAnimationRepeat(animation: Animator) {}
})
animator.interpolator = AccelerateDecelerateInterpolator()
animator.duration = duration
animator.start()
}
}
fun View.expandAnimation(duration: Long) {
measure(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
val initialHeight = 0
val targetHeight = measuredHeight
layoutParams.height = 0
animateView(this, duration, initialHeight, targetHeight)
}
fun View.collapseAnimation(duration: Long) {
val initialHeight = measuredHeight
val targetHeight = 0
animateView(this, duration, initialHeight, targetHeight) {
hide()
}
}
fun View.hide() {
this.apply {
visibility = View.GONE
}
}
fun View.show() {
this.apply {
visibility = View.VISIBLE
}
}
You can easily convert this code to java
sry I don't have time to convert it myself
Related
I'm making a recipe search application using forkify API. I get such json (let's take pizza recipes for example). I've made a recycler and searchable, but the recipes themselves are given as a link to the site with that recipe (see source_url in the json). I've made a webview for this, but there's one problem. I need to get that source_url and have it match the recipe I clicked on. I tried to make an additional element in resycler, small invisible textview, and put source_url there, so when I clicked on it, it would take text and pass it to a variable and load it as url into webview. (Very silly solution, but I didn't think of another one.) It's not what I had in mind. Basically my code works, but the url is not passed from all textViews. I've been observing its behaviour and I can only assume that it loads every 4 in vertical mode and every 2 in horizontal mode. And this is not what I need. Please help me to solve this problem. Below is my code:
Adapter:
#JvmOverloads
fun RecyclerView.affectOnItemClicks(
onClick: ((position: Int, view: View) -> Unit)? = null,
onLongClick: ((position: Int, view: View) -> Unit)? = null
) {
this.addOnChildAttachStateChangeListener(
RecyclerItemClickListener(
this,
onClick,
onLongClick
)
)
}
class RecyclerAdapter(
private val dataset: List<Recipe>
)
: RecyclerView.Adapter<RecyclerAdapter.FoodHolder>() {
inner class FoodHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindRecipe(recipe: Recipe) {
itemView.textView.text = recipe.title
itemView.textView3.text = recipe.publisher
itemView.imageView.load(recipe.image_url) {
// placeholder image is the image used
// when our image url fails to load.
placeholder(R.drawable.ic_baseline_error_24)
}
itemView.helptv.text = recipe.source_url
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.FoodHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recyclerview_item_row, parent, false)
return FoodHolder(view)
}
override fun onBindViewHolder(holder: RecyclerAdapter.FoodHolder, position: Int) {
holder.bindRecipe(dataset.get(position))
}
override fun getItemCount(): Int = dataset.size
}
The code in the MainActivity where I put the text from that textview into an auxiliary variable and then switch to another activation:
ConstandVar.browser_url = helptv.text.toString()
val intent = Intent(this,BrowserActivity::class.java)
startActivity(intent)
layout recyclerview:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<com.google.android.material.card.MaterialCardView
android:id="#+id/materialCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:clickable="false"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:state_dragged="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/item_constraint"
android:layout_width="match_parent"
android:layout_height="120dp"
android:padding="5dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="#tools:sample/avatars" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="90dp"
android:layout_marginTop="5dp"
android:text="Title"
android:textColor="#000000"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="publisher: The Pioner Women"
android:textColor="#E57373"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/helptv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="1sp"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Receive json method:
fun getRecipe(callback: (List) -> Unit) {
val apiService = AppModule.provideRetrofitInstance(ConstandVar.BASE_URL)
apiService.getRecipe(food).enqueue(object : Callback<requestdata> {
override fun onFailure(call: Call<requestdata>, t: Throwable) {
Log.d("tag", "getRecipe Error")
}
override fun onResponse(call: Call<requestdata>, response: Response<requestdata>) {
return response.body()!!.recipes?.let { callback(it) }!!
}
})
Any help would be much appreciated, thanks in advance!
Please make little bit change to make adapter like that way
read most of comment ,
RecyclerView itemClickListener in Kotlin
create callback listener and return url in main activity
I'm trying to create a form to capture data, I need to access the camera to take pictures. My problem is when I try to call the camera with imagenButton, it's not working but the code doesn't show any error.
Here's my fragment to declare form:
public class EspecimenesInsertarFragment extends Fragment implements
Response.Listener<JSONObject>, Response.ErrorListener {
private EspecimenesViewModel especimenesViewModel;
RequestQueue rq;
JsonRequest jrq;
final int COD_SELECCIONA=10;
final int COD_FOTO=20;
private static final int REQUEST_IMAGE_CAMERA=101;
private static final int REQUEST_PERMISSION_CAMERA=101;
Button btnGuardar, btnCancelar;
ImageButton btnCamara, btnGaleria;
ImageView imageView;
public static final int MY_DEFAULT_TIMEOUT = 50000;
public EspecimenesInsertarFragment() {
// Required empty public constructor
}
public static EspecimenesInsertarFragment newInstance() { return new EspecimenesInsertarFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view;
view = inflater.inflate(R.layout.fragment_colecciones_insertar, container, false);
imageView = (ImageView)view.findViewById(R.id.imageView);
btnCamara=(ImageButton) view.findViewById(R.id.tomarFoto);
btnGuardar = (Button) view.findViewById(R.id.buttonIngresarEspecimenes);
rq = Volley.newRequestQueue(getContext());
/* if(validaPermisos()){
btnCamara.setEnabled(true);
}else{
btnCamara.setEnabled(false);
} */
if (ContextCompat.checkSelfPermission(getContext(), WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA}, 1000);
}
btnGuardar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
registrar_especimen("http://localhost/BIO-UES-APP/EspecimenesController.php");
}
});
static final int REQUEST_TAKE_PHOTO=1;
public void tomarFoto(View view){
Intent takePictureInent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Log.d("entra","");
if(takePictureInent.resolveActivity(getActivity().getPackageManager())!= null){
File photoFile=null;
try {
photoFile=createImageFile();
}catch (IOException ex){
}
if(photoFile!=null){
Uri photoUri=FileProvider.getUriForFile(getActivity(),"com.example.luvin.drawercero",photoFile);
takePictureInent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
getActivity().startActivityForResult(takePictureInent,REQUEST_TAKE_PHOTO);
}
}
}
And this is my XML layout:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Especimenes.EspecimenesConsultarFragment">
<!-- TODO: Update blank fragment layout -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_centerVertical="true"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="-7dp"
android:layout_marginRight="-7dp"
android:layout_marginBottom="9dp"
tools:layout_editor_absoluteX="393dp"
tools:layout_editor_absoluteY="79dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageButton
android:id="#+id/tomarFoto"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginStart="100dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:clickable="true"
android:src="#android:drawable/ic_menu_camera" />
<ImageButton
android:id="#+id/seleccionarDesdeGaleria"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginStart="200dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:src="#android:drawable/ic_menu_gallery" />
</FrameLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="88dp"
android:orientation="vertical">
<Button
android:id="#+id/buttonCancelarEspecimenes"
android:layout_width="129dp"
android:layout_height="41dp"
android:layout_toRightOf="#+id/buttonIngresar"
android:backgroundTint="#96A6A8"
android:gravity="center|left"
android:text="CANCELAR"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.783"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.659" />
<Button
android:id="#+id/buttonIngresarEspecimenes"
android:layout_width="129dp"
android:layout_height="41dp"
android:layout_marginStart="68dp"
android:text="INGRESAR"
app:backgroundTint="#00BCD4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/buttonCancelar"
app:layout_constraintHorizontal_bias="0.85"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.659" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</ScrollView>
Logcat message when button is pressed:
com.example.luvin.drawercero D/ViewRootImpl#6731d38[MainActivity]: ViewPostIme pointer 1
To complete my question, I have the permissions in the manifest. I already tried to call the camera in another way, tried creating the method in the MainActivity to create the OnClick event in the XML Layout, but nothing works.
If anyone knows how to solve this issue please help.
Thanks.
You forgot to add the on click listener to your photo button. This should solve your problem:
btnCamara = view.findViewById(R.id.tomarFoto);
btnCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tomarFoto(v);
}
});
Good day - I'm new to recyclerViews and connecting to Room database. I've got one working with the help from a tutorial and now I want to add to it. My aim is to:
Implement a Room database which in turn presents data to the user via a recyclerView.
Have 1 recyclerView in the main activity and a 2nd recyclerView in a second activity. I'm trying to have a different layout in each activity as shown in the following links.
Main activity:
Second activity:
The issue I'm having is even though the XML files are unique for each activity, along with the variables within, the name of the recyclerView, and also the methods for each activity, the layout in the second activity shows in the first activity.
activity_main has the following:
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="100dp"
android:id="#+id/recycler_view111"
android:layout_width="match_parent"
android:layout_height="114dp"
tools:listitem="#layout/testing" />
The second activity XML file has the following:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="488dp"
tools:listitem="#layout/testing1_item" />
Can someone please help me identify why the same recyclerView is shown across the 2 activities please?
To trouble-shoot, I've:
Gone through all the XML files to ensure there is no issue with the names of the files/methods etc.
Copied the layout from the activity_main xml and applied it to the second xml file. This then in turn displayed the layout that I'm testing within in MainActivity across both activities.
MainActivity uses the activity_main.xml which uses a test file called testing.xml - code as follows:
MainActivity:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(getApplicationContext(), AllWordsActivity.class);
startActivity(intent);
}
});
RecyclerView recyclerView111 = findViewById(R.id.recycler_view111);
recyclerView111.setLayoutManager(new LinearLayoutManager(this));
recyclerView111.setHasFixedSize(true);
NoteAdapter adapter = new NoteAdapter();
recyclerView111.setAdapter(adapter);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginTop="500dp"
android:layout_marginRight="50dp"
android:background="#color/cardview_shadow_start_color"
android:maxLines="1"
android:text="Open new Activity!"
android:textColor="#color/black"
android:textSize="20dp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="100dp"
android:id="#+id/recycler_view111"
android:layout_width="match_parent"
android:layout_height="114dp"
tools:listitem="#layout/testing" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
testing.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_priority1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:textColorHighlight="#color/black"
android:text="1"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/text_view_title1"
android:layout_width="323dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginStart="183dp"
android:layout_toStartOf="#id/text_view_priority1"
android:ellipsize="end"
android:maxLines="1"
android:text="Title1"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/text_view_description1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="#id/text_view_title1"
android:text="Description1" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
The second activity is based on a class called AllWordsActivity" which uses activity_all_words which uses note_item test - code as follows:
AllWordsActivity.java
private NoteViewModel noteViewModel;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_words);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
NoteAdapter adapter = new NoteAdapter();
recyclerView.setAdapter(adapter);
//noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
activity_all_words.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".AllWordsActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="488dp"
tools:listitem="#layout/note_item" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
note_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_priority"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:textColor="#color/purple_500"
android:text="1"
android:textAppearance="#style/TextAppearance.AppCompat.Large"/>
<TextView
android:id="#+id/text_view_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Title"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:maxLines="1"
android:layout_toStartOf="#id/text_view_priority"
android:layout_alignParentStart="true"
android:ellipsize="end"/>
<TextView
android:id="#+id/text_view_description"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_below="#id/text_view_title"
android:text="Description" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
Code for noteAdapter:
```public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder>
{
private List notes = new ArrayList<>();
#NonNull
#Override
public NoteHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_item, parent, false);
return new NoteHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull NoteHolder holder, int position)
{
Note currentNote = notes.get(position);
holder.textViewTitle.setText(currentNote.getTitle());
holder.textViewDescription.setText(currentNote.getDescription());
holder.textViewPriority.setText(String.valueOf(currentNote.getPriority()));
}
#Override
public int getItemCount()
{
return notes.size();
}
public void setNotes(List<Note> notes)
{
this.notes = notes;
notifyDataSetChanged();
}```
The problem is that both activities use the same adapter for their list view: NoteAdapter adapter = new NoteAdapter();. In turn, NoteAdapter only inflates note_item.xml for each item in the list:
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_item, parent, false);
To fix this, you need to either change NoteAdapter to work with multiple layout files for its rows. Or you need to create a different adapter for each RecyclerView.
Original Answer:
It sounds like you are seeing the same items displaying in both of your recycler views. The problem is that both the MainActivity and the AllWordsActivity have these lines:
NoteAdapter adapter = new NoteAdapter();
recyclerView.setAdapter(adapter);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
So both activities are getting data from the same ViewModel to display. To display different data, use a different ViewModel in the MainActivity.
p.s. I suggest using consistent naming. You have AllWordsActivity and NotesAdapater. Either use AllWords or Notes, but don't mix and match.
I want to achieve expand and collapse in RecyclerView as mentioned in gif. By taping and swiping down & up.
I have tried below,
https://stackoverflow.com/a/13381228/11630822
that is fine but not what I expected.
I have used RecyclerView for listing all Notification inside the app. If anyone have any ideas or experience , then please share with me. Any help will be appreciated. Thanks in advance.
In most of the sites, able to find way to acheive swipe left and right, but not swipe up and down. I want to achieve swipe up and down as like swipe left and swipe right.
In the gif I didnt use arrow for expand and collapse, I just swiped up and down. I want to achieve the samething in recyclerview inside the app.
You can use Transition or Animator that changes visibility of section to be expanded/collapsed, or ConstraintSet with different layouts.
Easiest one is to use motionLayout with different to layouts and constraintSets to change from one layout to another on button click. You can change between layouts with
val constraintSet = ConstraintSet()
constraintSet.clone(this, R.layout.layout_collapsed)
val transition = ChangeBounds()
transition.interpolator = AccelerateInterpolator(1.0f)
transition.setDuration(300)
TransitionManager.beginDelayedTransition(YOUR_VIEW, transition)
constraintSet.applyTo(YOUR_VIEW)
Expansion/collapse animation in gif with using Transitions that changes direction of button with rotating x, and expand/collapse setting item visibility and starting TransitionManager.beginDelayed transition
RotateX.kt
class RotateX : Transition {
#Keep
constructor() : super()
#Keep
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
override fun getTransitionProperties(): Array<String> {
return TRANSITION_PROPERTIES
}
override fun captureStartValues(transitionValues: TransitionValues) {
captureValues(transitionValues)
}
override fun captureEndValues(transitionValues: TransitionValues) {
captureValues(transitionValues)
}
override fun createAnimator(
sceneRoot: ViewGroup,
startValues: TransitionValues?,
endValues: TransitionValues?
): Animator? {
if (startValues == null || endValues == null) return null
val startRotation = startValues.values[PROP_ROTATION] as Float
val endRotation = endValues.values[PROP_ROTATION] as Float
if (startRotation == endRotation) return null
val view = endValues.view
// ensure the pivot is set
view.pivotX = view.width / 2f
view.pivotY = view.height / 2f
return ObjectAnimator.ofFloat(view, View.ROTATION_X, startRotation, endRotation)
}
private fun captureValues(transitionValues: TransitionValues) {
val view = transitionValues.view
if (view == null || view.width <= 0 || view.height <= 0) return
transitionValues.values[PROP_ROTATION] = view.rotationX
}
companion object {
private const val PROP_ROTATION = "iosched:rotate:rotation"
private val TRANSITION_PROPERTIES = arrayOf(PROP_ROTATION)
}
}
create xml file that targets expand button
<?xml version="1.0" encoding="utf-8"?>
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:interpolator/fast_out_slow_in">
<transition class="com.smarttoolfactory.tutorial3_1transitions.transition.RotateX">
<targets>
<target android:targetId="#id/ivExpand" />
</targets>
</transition>
<autoTransition android:duration="200" />
</transitionSet>
My layout to be expanded or collapsed
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_marginVertical="2dp"
android:clickable="true"
android:focusable="true"
android:transitionName="#string/transition_card_view"
app:cardCornerRadius="0dp"
app:cardElevation="0dp"
app:cardPreventCornerOverlap="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="#drawable/avatar_1_raster" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivExpand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_baseline_expand_more_24" />
<TextView
android:id="#+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:text="Some Title"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="#+id/ivAvatar"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="?android:textColorSecondary"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="#+id/tvTitle"
app:layout_constraintTop_toBottomOf="#id/tvTitle"
tools:text="Tuesday 7pm" />
<TextView
android:id="#+id/tvBody"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:lines="1"
android:text="#string/bacon_ipsum_short"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/ivAvatar"
app:layout_constraintTop_toBottomOf="#id/tvDate" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:orientation="horizontal"
android:overScrollMode="never"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tvBody"
tools:listitem="#layout/item_image_destination" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
Change visibility of items to collapse or expand with
private fun setUpExpandedStatus() {
if (isExpanded) {
binding.recyclerView.visibility = View.VISIBLE
binding.ivExpand.rotationX = 180f
} else {
binding.recyclerView.visibility = View.GONE
binding.ivExpand.rotationX = 0f
}
}
Start animation
val parent = (itemView.parent as? ViewGroup)
val transition = TransitionInflater.from(itemView.context)
.inflateTransition(R.transition.icon_expand_toggle)
TransitionManager.beginDelayedTransition(parent, transition)
isExpanded = !isExpanded
setUpExpandedStatus()
I created animation and transitions samples including the one on the gif, you can check them out there.
My layout_xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="#dimen/_350sdp"
android:maxHeight="#dimen/_500sdp"
android:orientation="vertical"
android:id="#+id/commentProblemScreenLL">
<ListView
android:id="#+id/commentProblemLV"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/commentProblemNotFound"
android:visibility="gone"
android:id="#+id/commentProblemNotFoundTV"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="#dimen/_40sdp"
android:background="#drawable/side_nav_bar"
android:orientation="horizontal"
android:padding="#dimen/m1dp"
android:weightSum="1"
android:layout_alignParentBottom="true">
<EditText
android:id="#+id/commentEditTextET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:background="#null"
android:hint="#string/comment_EditText"
android:padding="5dip"
android:textColor="#color/white"
android:textColorHint="#color/hintcolor" />
<ImageButton
android:id="#+id/commentSendTextIB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:layout_alignParentEnd="true"
android:background="#drawable/side_nav_bar"
android:paddingBottom="#dimen/_4sdp"
android:src="#drawable/cm_chat_send"
android:layout_alignParentRight="true"
android:paddingRight="#dimen/_10sdp"
android:layout_marginTop="#dimen/_5sdp"/>
</RelativeLayout>
</RelativeLayout>
Java code:-
private void showCommentDailog()
{
Log.d(TAG,"showCommentDailog enter()");
commentDialog = new BottomSheetDialog(getContext());
View view = ((ProblemsDetailActivity) getActivity()).getLayoutInflater().inflate(R.layout.commentproblemscreen, null);
commentDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
commentProblemLV = (ListView)view.findViewById(R.id.commentProblemLV);
TextView commentProblemNotFoundTV = (TextView)view.findViewById(R.id.commentProblemNotFoundTV);
EditText commentEditTextET = (EditText) view.findViewById(R.id.commentEditTextET);
ImageButton commentSendTextIB = (ImageButton)view.findViewById(R.id.commentSendTextIB);
if(commentDialog.getWindow() != null) {
commentDialog.getWindow().setGravity(Gravity.BOTTOM);
}
//call the function to show list of previous work
commentDialog.setContentView(view);
commentDialog.setCanceledOnTouchOutside(true);
commentDialog.show();
final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from((View) view.getParent());
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
commentDialog.dismiss();
}else{
if (newState != BottomSheetBehavior.STATE_EXPANDED) {
if(commentProblemLV != null && !listIsAtTop()){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
}
This code does not show the full layout in bottomsheetDailog. Please correct my code as it shows the full layout in bottomsheetDialog.
I want to open full layout in half screen with BottomSheetDialog.
here I should be given my java code also for bottomSheetDialog.
bottomsheetdailog will apear on clickof comment ImageView.