I want to use an expandableRecyler but when i use the adapter it doesnt work. It doesnt give me any error or anything. just doesnt appear on the screen
I have this Fragment where i call the recyclerView
public class RecFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
Button btaddrec;
Dialog alerta;
View v;
RecyclerView rvRec;
public RecFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment RecFragment.
*/
// TODO: Rename and change types and number of parameters
public static RecFragment newInstance(String param1, String param2) {
RecFragment fragment = new RecFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_rec, container, false);
rvRec = v.findViewById(R.id.recyclerviewRec);
btaddrec = (Button) v.findViewById(R.id.btaddRec);
initData();
setRecycler();
btaddrec.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), MainActivity.listarec.size() + "", Toast.LENGTH_SHORT).show();
}
});
return v;
}
private void setRecycler(){
RecyclerRec recyclerRec = new RecyclerRec(MainActivity.listarec);
rvRec.setLayoutManager(new LinearLayoutManager(getActivity()));
rvRec.setAdapter(recyclerRec);
rvRec.setHasFixedSize(true);
}
private void initData(){
MainActivity.listarec.add(new Recordatorio("Homework","Math and Science Homewowk","14:00"));
MainActivity.listarec.add(new Recordatorio("Homework","Math and Science Homewowk","14:00"));
}
}
Function initData add some objects to my list (i have checked that it works with the Button, my list has 2 items)
Function setRecycler set the adapter for the recyclerview
This is my class RecyclerRec
public class RecyclerRec extends RecyclerView.Adapter<RecyclerRec.RecVh>{
ArrayList<Recordatorio> listarec;
public RecyclerRec (ArrayList<Recordatorio> lista){
this.listarec = lista;
}
#NonNull
#Override
public RecVh onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rec_layout,parent,false);
return new RecVh(v);
}
#Override
public void onBindViewHolder(#NonNull RecVh holder, int position) {
Recordatorio rec = listarec.get(position);
holder.tvTitulo.setText(rec.getTitulo());
holder.tvCuerpo.setText(rec.getCuerpo());
holder.tvHora.setText(rec.getHora());
boolean expanded = rec.isExpanded();
holder.expandable.setVisibility(expanded ? View.VISIBLE : View.GONE);
}
#Override
public int getItemCount() {
return listarec.size();
}
public class RecVh extends RecyclerView.ViewHolder {
TextView tvTitulo,tvCuerpo,tvHora;
LinearLayout linearLayout;
ConstraintLayout expandable;
public RecVh(#NonNull View itemView) {
super(itemView);
tvTitulo = itemView.findViewById(R.id.tvTituloRec);
tvCuerpo = itemView.findViewById(R.id.tvCuerpo);
tvHora = itemView.findViewById(R.id.tvHoraRec);
linearLayout = itemView.findViewById(R.id.linearlayotuexpand);
expandable = itemView.findViewById(R.id.expandableRec);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Recordatorio rec = listarec.get(getAdapterPosition());
rec.setExpanded(!rec.isExpanded());
notifyItemChanged(getAdapterPosition());
}
});
}
}
}
XML of fragment
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.ClasesFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerviewRec"
android:layout_width="match_parent"
android:layout_height="451dp"
android:layout_marginTop="50dp" />
<Button
android:id="#+id/btaddRec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="160dp"
android:layout_marginTop="520dp"
android:text="AƱadir" />
(Framelayout tag is closed correctly, dunno why stackoverflow doesnt write it with ctrl+k)
XML of my item/row
<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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/tvTituloRec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:padding="10dp"
android:text="Titulo Recordatorio"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:textColor="#android:color/black"
android:textStyle="bold"
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/tvHoraRec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hora"
android:textSize="17dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/expandableRec"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tvTituloRec">
<TextView
android:id="#+id/tvCuerpo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:text="Cuerpo del recordatorio"
android:textAppearance="#style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toEndOf="#+id/textView"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
All seems to be in order but when i run the app it doesnt appear and doesnt give me any error.
Related
I have the following classes:
CategoryFragment.java
public class CategoryFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "category_name";
// TODO: Rename and change types of parameters
private int mParam1;
public CategoryFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #return A new instance of fragment CategoryFragment.
*/
// TODO: Rename and change types and number of parameters
public static CategoryFragment newInstance(int param1) {
CategoryFragment fragment = new CategoryFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getInt(ARG_PARAM1);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Context context = getActivity();
View view = inflater.inflate(R.layout.listado_noticias, container, false);
RecyclerView rw_noticias = view.findViewById(R.id.rw_noticias);
new LoadArticlesTask().execute(MainScreen.mPrefs,MainScreen.hasRemember,view,context,rw_noticias);
return null;
}
}
listado_noticias.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/constraintLayout"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rw_noticias"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
LoadArticlesTask.java
public class LoadArticlesTask extends AsyncTask<Object, Void, List<Article>> {
private static final String TAG = "LoadArticlesTask";
private View view;
private Context context;
private RecyclerView rw_noticias;
#Override
protected List<Article> doInBackground(Object... params) {
SharedPreferences sp = (SharedPreferences)params[0];
boolean hasRemember = (boolean)params[1];
view = (View)params[2];
context = (Context)params[3];
rw_noticias = (RecyclerView)params[4];
List<Article> res = null;
Properties ini = new Properties();
ini.setProperty(RESTConnection.ATTR_SERVICE_URL,Constants.URL_SERVICE);
ini.setProperty(RESTConnection.ATTR_REQUIRE_SELF_CERT,Constants.CERT_VALUE);
ModelManager.configureConnection(ini);
String strIdUser;
String strApiKey;
String strIdAuthUser;
if(hasRemember){
strIdUser = sp.getString("pref_apikey","");
strApiKey = sp.getString("pref_IdUser","");
strIdAuthUser = sp.getString("pref_strIdAuthUser","");
}else {
strIdUser = ModelManager.getLoggedIdUSer();
strApiKey = ModelManager.getLoggedApiKey();
strIdAuthUser = ModelManager.getLoggedAuthType();
}
//ModelManager uses singleton pattern, connecting once per app execution in enough
if (!ModelManager.isConnected()){
// if it is the first login
if (strIdUser==null || strIdUser.equals("")) {
try {
ModelManager.login(Constants.USER, Constants.PASS);
} catch (AuthenticationError e) {
Log.e(TAG, e.getMessage());
}
}
// if we have saved user credentials from previous connections
else{
ModelManager.stayloggedin(strIdUser,strApiKey,strIdAuthUser);
}
}
//If connection has been successful
if (ModelManager.isConnected()) {
try {
// obtain 6 articles from offset 0
res = ModelManager.getArticles(6, 0);
for (Article article : res) {
// We print articles in Log
Log.i(TAG, String.valueOf(article));
}
} catch (ServerCommunicationError e) {
Log.e(TAG,e.getMessage());
}
}
return res;
}
#Override
protected void onPostExecute(List<Article> articles) {
super.onPostExecute(articles);
Log.i("Articles", articles.toString());
for (Article article : articles) {
// We print articles in Log
Log.i("Articles", String.valueOf(article));
}
refreshList(articles,view);
}
public void refreshList(List<Article> data, View view){
if (data == null){
return;
}
for (Article article : data) {
// We print articles in Log
Log.i("Articles_rl", String.valueOf(article));
}
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rw_noticias.setLayoutManager(layoutManager);
ArticlesAdapter articlesAdapter = new ArticlesAdapter(data);
rw_noticias.setAdapter(articlesAdapter);
((ArticlesAdapter)rw_noticias.getAdapter()).updateData(data);
}
}
ArticlesAdapter.java
public class ArticlesAdapter extends RecyclerView.Adapter<ArticlesAdapter.ArticleViewHolder>{
private List<Article> articulos;
public ArticlesAdapter(List<Article> articulos){
this.articulos = articulos;
}
#NonNull
#Override
public ArticleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout_article, parent, false);
return new ArticleViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ArticleViewHolder holder, int position) {
Bitmap imagen = null;
holder.category.setText(articulos.get(position).getCategory());
holder.title.setText(articulos.get(position).getTitleText());
holder.resumen.setText(articulos.get(position).getAbstractText());
try {
imagen = SerializationUtils.base64StringToImg(articulos.get(position).getImage().getImage());
} catch (ServerCommunicationError serverCommunicationError) {
serverCommunicationError.printStackTrace();
}
holder.thumbnail.setImageBitmap(imagen);
}
#Override
public int getItemCount() {
return articulos.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public void updateData(List<Article>data){
articulos.clear();
articulos.addAll(data);
notifyDataSetChanged(); //notify to repaint the list
}
public void articlesFilterCategory(String category){
for (Article a : articulos){
if(!category.equals("ALL") && !a.getCategory().equals(category)){
articulos.remove(a);
}
}
}
public static class ArticleViewHolder extends RecyclerView.ViewHolder{
CardView cv;
TextView category;
TextView title;
TextView resumen;
ImageView thumbnail;
public ArticleViewHolder(#NonNull View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.card_article);
category = (TextView)itemView.findViewById(R.id.category_noticia);
resumen = (TextView)itemView.findViewById(R.id.resumen_noticia);
thumbnail = (ImageView)itemView.findViewById(R.id.thumbnail);
}
}
}
card_layout_article.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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?attr/selectableItemBackground"
android:ellipsize="end"
android:id="#+id/card_article"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingHorizontal="1dp">
<ImageView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="231dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:adjustViewBounds="true"
android:background="#drawable/a15877171854035"
android:cropToPadding="true"
android:scaleType="fitXY"
android:src="#drawable/degradado" />
<View
android:layout_width="match_parent"
android:layout_height="233dp"
android:background="#drawable/degradado" />
<TextView
android:id="#+id/title_noticia"
android:layout_width="193dp"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="107dp"
android:layout_marginEnd="107dp"
android:layout_marginBottom="95dp"
android:text="Nuevo caso de coronavirus"
android:textAlignment="center"
android:textColor="#color/cardview_light_background"
android:textSize="20dp"
android:textStyle="bold" />
<TextView
android:id="#+id/category_noticia"
android:layout_width="91dp"
android:layout_height="31dp"
android:layout_alignBottom="#+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="11dp"
android:layout_marginEnd="316dp"
android:layout_marginBottom="145dp"
android:text="NATIONAL"
android:textAlignment="center"
android:textColor="#color/cardview_light_background"
android:textSize="15dp"
android:textStyle="bold" />
<TextView
android:id="#+id/resumen_noticia"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_alignBottom="#+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="-1dp"
android:text="Nuevo caso de coronavirus"
android:textAlignment="viewStart"
android:textColor="#color/cardview_light_background"
android:textSize="11dp"
android:textStyle="bold" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
In the log.i that I have in the Post Execute of the async task I can see how the articles are formed (The Article class has a toString () function).
But I can't get the articles to be seen in the RecyclerView. What am I doing wrong?
Capture: Main screen with recyclerView empty...
Thanks!
Pass the instance of RecyclerView like -
new LoadArticlesTask().execute(MainScreen.mPrefs, MainScreen.hasRemember, view, rw_noticias, context);
Receive this on LoadArticlesTask as you are doing with View.
Don't re-initialize/use this code inside your class -
RecyclerView rw_noticias = view.findViewById(R.id.rw_noticias);
In your card_layout_article.xml, make height wrap_content for cardview:
<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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
........
........
Also in the layout of your recycler view instead of ConstraintLayout try to use RelativeLayout as the parent:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/constraintLayout"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rw_noticias"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
I have a RecyclerView inside BottomSheetDialogFragment. The RecyclerView items touch working normally when it's scrolling slowly.
But when the RecyclerView is scrolled fast and after the list stops (without touching), than touching on any item doesn't work on fast touch. It needs double touching.
See in the below example gif, when touching on Andhra Pradesh it's working fine. After slow scrolling, touching on Haryana also works fine. Then doing a fast scroll and touching on Punjab doesn't work on the first touch. Touching again it works.
Following is the code:
OperatorListDialogFragment.java
package com.*;
import *;
public class OperatorListDialogFragment extends BottomSheetDialogFragment{
private static final String ARG_NAME = "item_name";
private static final String ARG_LOGO = "item_logo";
private Listener mListener;
private String header;
private Context mContext;
public static OperatorListDialogFragment newInstance(String[] name, int[] logo, String header) {
final OperatorListDialogFragment fragment = new OperatorListDialogFragment();
final Bundle args = new Bundle();
args.putStringArray(ARG_NAME, name);
args.putIntArray(ARG_LOGO, logo);
args.putString("header", header);
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_operator_list_dialog_list_dialog, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
TextView headerTV = view.findViewById(R.id.title);
headerTV.setText(getArguments().getString("header"));
final RecyclerView recyclerView = view.findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new OperatorAdapter(getArguments().getStringArray(ARG_NAME), getArguments().getIntArray(ARG_LOGO)));
view.findViewById(R.id.dismiss).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
final Fragment parent = getParentFragment();
if (parent != null) {
mListener = (Listener) parent;
} else {
mListener = (Listener) context;
}
}
#Override
public void onDetach() {
mListener = null;
super.onDetach();
}
public interface Listener {
void onFilterSelected(String selected, String selectedQuery);
}
private class ViewHolder extends RecyclerView.ViewHolder {
final TextView text;
ImageView logo;
ViewHolder(LayoutInflater inflater, ViewGroup parent) {
// TODO: Customize the item layout
super(inflater.inflate(R.layout.fragment_operator_list_dialog_list_dialog_item, parent, false));
text = itemView.findViewById(R.id.tv_operator_name);
logo = itemView.findViewById(R.id.iv_recharge_provider_icon);
}
}
private class OperatorAdapter extends RecyclerView.Adapter<ViewHolder> {
private String[] mNames;
private int[] mLogos;
OperatorAdapter(String[] name, int[] logo) {
mNames = name;
mLogos = logo;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.text.setText(mNames[position]);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("clicked", "" + position);
}
});
}
#Override
public int getItemCount() {
return mNames.length;
}
}
}
dialog.xml
<?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_height="match_parent"
android:layout_width="match_parent"
>
<ImageView
android:focusable="true"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="#+id/dismiss"
android:padding="14dp"
android:src="#drawable/ic_close_black_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/title"
app:layout_constraintTop_toTopOf="#id/dismiss"
app:layout_constraintBottom_toBottomOf="#id/dismiss"
app:layout_constraintLeft_toRightOf="#id/dismiss"
android:padding="14dp"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
tools:text="Select operator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
app:layout_constraintTop_toBottomOf="#id/dismiss"
android:background="#969696"
android:layout_width="match_parent"
android:layout_height="0.5dp"/>
<androidx.recyclerview.widget.RecyclerView
app:layout_constraintTop_toBottomOf="#id/dismiss"
app:layout_constraintBottom_toBottomOf="parent"
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_constrainedHeight="true"
android:paddingTop="#dimen/list_item_spacing_half"
android:paddingBottom="#dimen/list_item_spacing_half"
tools:context=".fragments.OperatorListDialogFragment"
tools:listitem="#layout/fragment_operator_list_dialog_list_dialog_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
recycler_item.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:gravity="center_vertical"
android:orientation="horizontal"
android:id="#+id/ll_operator_list_wrapper"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:visibility="gone"
android:layout_marginLeft="16dp"
android:id="#+id/iv_recharge_provider_icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginVertical="16dp"
android:layout_centerVertical="true"
android:src="#drawable/ic_bsnl_logo"
tools:visibility="visible"/>
<TextView
android:padding="16dp"
android:textColor="#212121"
android:textSize="14sp"
android:ellipsize="end"
android:id="#+id/tv_operator_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="false"
android:text="BSNL"
android:layout_toRightOf="#+id/iv_recharge_provider_icon"
android:layout_centerInParent="true"/>
<View
android:layout_below="#id/iv_recharge_provider_icon"
android:id="#+id/divider0"
android:background="#eeeeee"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_marginLeft="16dp"
android:layout_toRightOf="#+id/iv_recharge_provider_icon"
/>
</RelativeLayout>
add android:nestedScrollingEnabled="false" in RecyclerView
Probably I am missing something here, but I am animating a recyclerview to outside of its container and when it is in the final position, the click events are not triggered, neither the scroll works...
I am using the ObjectAnimator to translate it, so I thought the clickable areas were also translated. Here is the relevant code:
The Fragment
public class SlideListFragment extends Fragment {
private Button slideButton;
private RecyclerView listToSlide;
private DummyListAdapter listAdapter;
private LinearLayout listContainer;
public static SlideListFragment newInstance() {
return new SlideListFragment();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.slide_list_fragment, container, false);
slideButton = root.findViewById(R.id.slide_up_btn);
slideButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
slideUpRoomsList();
}
});
listToSlide = root.findViewById(R.id.list_to_slide);
listContainer = root.findViewById(R.id.list_container);
setupList();
return root;
}
private void setupList() {
GridLayoutManager layoutManager = new GridLayoutManager(this.getContext(), 1);
layoutManager.setReverseLayout(true);
listToSlide.setLayoutManager(layoutManager);
listAdapter = new DummyListAdapter(this.getContext());
listToSlide.setAdapter(listAdapter);
setListData(5);
}
private void setListData(int i) {
ArrayList<DummyModel> items = new ArrayList<>();
for (int j = 0; j < i; j++) {
items.add(new DummyModel(j, "TEXT" + j));
}
listAdapter.refreshItems(items);
}
private void slideUpRoomsList() {
float height = listContainer.getHeight();
ObjectAnimator showAnimation = ObjectAnimator.ofFloat(listContainer, "translationY", -height);
showAnimation.setDuration(500);
showAnimation.start();
}
}
The Fragment Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:id="#+id/slidelist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
tools:context=".ui.slidelist.SlideListFragment">
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8" />
<android.support.constraint.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#FF0000"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline">
<LinearLayout
android:id="#+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/list_to_slide"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
<Button
android:id="#+id/slide_up_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="SlideUp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
The Adapter
public class DummyListAdapter extends RecyclerView.Adapter<DummyListAdapter.ViewHolder> {
private WeakReference<Context> mContext;
private ArrayList<DummyModel> data;
public DummyListAdapter(Context ctx) {
mContext = new WeakReference<>(ctx);
}
#NonNull
#Override
public DummyListAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.dummy_list_item, parent, false);
DummyListAdapter.ViewHolder vh = new DummyListAdapter.ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(#NonNull DummyListAdapter.ViewHolder holder, int position) {
// get element from your dataset at this position
final DummyModel item = data.get(position);
// replace the contents of the view with that element
holder.labelTV.setText(item.getText());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext.get(), "Item Clicked: "+ item.getText(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return data != null ? data.size() : 0;
}
public void refreshItems(ArrayList<DummyModel> items) {
this.data = items;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView labelTV;
public ViewHolder(View itemView) {
super(itemView);
this.labelTV = itemView.findViewById(R.id.label_tv);
}
}
}
The List Item Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<TextView
android:id="#+id/label_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
android:textSize="20sp"
android:textColor="#0000FF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
What is happening in this case?
UPDATE
I am doing some debug and I noticed that the problem is because the end position is outside the list container. If I translate inside the container, it works properly. So my new question is: how can I translate a view outside of the container, while still having the click events triggered?
Basically, I just gave up on this approach. I changed my layout so it list has space to show up inside its container.
I'm trying to adapt a recyclerview to display a list of objects. But actually I have some kind of wierd bug. My object have ID and Name data to display, but in the list, at first, I only can see the Id, and when I scroll down, only the rows going completely out of the screen are completely displayed...
This is my ListPresentActivity.
public class ListPresentActivity extends AppCompatActivity implements ViewInterface {
private static final String EXTRA_PRESENT_ID = "EXTRA_PRESENT_ID";
private static final String EXTRA_PRESENT_NAME = "EXTRA_PRESENT_NAME";
private List<PresentItem> listOfPresent;
private LayoutInflater layoutInflater;
private RecyclerView recyclerView;
private CustomAdapter adapter;
private PresentController presentController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_present);
recyclerView = (RecyclerView) findViewById(R.id.rec_list_activity);
recyclerView.setHasFixedSize(true);
layoutInflater = getLayoutInflater();
presentController = new PresentController(this, new FakePresentModel());
}
#Override
public void startDetailActivity(int id, String name, String info, String target, String advice, String price) {
//public void startDetailActivity(int id) {
Intent i = new Intent(this,PresentDetailActivity.class);
i.putExtra(EXTRA_PRESENT_ID, id);
i.putExtra(EXTRA_PRESENT_NAME, name);
startActivity(i);
}
#Override
public void setUpAdapterAndView(List<PresentItem> listOfPresent) {
this.listOfPresent = listOfPresent;
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new CustomAdapter();
recyclerView.setAdapter(adapter);
}
private class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder>{
#Override
public CustomAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = layoutInflater.inflate(R.layout.item_present, parent, false);
return new CustomViewHolder(v);
}
#Override
public void onBindViewHolder(CustomAdapter.CustomViewHolder holder, int position) {
PresentItem currentPresent = listOfPresent.get(position);
holder.id.setText(
Integer.toString(currentPresent.getId())
);
holder.name.setText(
currentPresent.getName()
);
}
#Override
public int getItemCount() {
return listOfPresent.size();
}
class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView id;
private TextView name;
private ViewGroup container;
public CustomViewHolder(View itemView){
super(itemView);
this.id = (TextView) itemView.findViewById(R.id.texv_item_id);
this.name = (TextView) itemView.findViewById(R.id.texv_item_name);
this.container = (ViewGroup) itemView.findViewById(R.id.root_list_present);
this.container.setOnClickListener(this);
}
#Override
public void onClick(View v) {
PresentItem presentItem = listOfPresent.get(
this.getAdapterPosition()
);
presentController.onListItemClick(presentItem);
}
}
}
}
The layout item_present.xml
<android.support.constraint.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="88dp"
android:id="#+id/root_list_present"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/texv_item_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:textSize="48sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="#id" />
<TextView
android:id="#+id/texv_item_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="84dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="collier" />
</android.support.constraint.ConstraintLayout>
And my list layout
<android.support.constraint.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="match_parent"
tools:context="net.lubbee.bruh.view.ListPresentActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/rec_list_activity"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
I have search for a long time now, and the only concording result I have fount seems to be fixed with the recyclerView.setHasFixedSize(true); which is not my case...
Thanks for your time!
PS : If there is some code parts needed missing, just say the word! :]
Just after the first loading.
After one scroll to the bottom and back to the top of the screen
<LinearLayout android:layout_width="match_parent"
android:layout_height="88dp"
android:weightSum="1"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_gravity="center_vertical"
android:layout_weight="0.2"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<TextView
android:layout_gravity="center_vertical"
android:layout_weight="0.8"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</LinearLayout>
Try this simple LinearLayout it should work
You can also add other properties, but for now try it out
I'm making a simple flashcard app using a ViewPager, FragmentStatePagerAdapter, and some card flipping animations found on the offical Android tutorials (https://developer.android.com/training/animation/cardflip.html). I've created a shuffle button which shuffles the cards in the deck and then calls notifyDataSetChanged on the adapter to update the card views. Once called, it successfully updates the views, but it also creates a shadow/border around each card that doesn't clear until the card is touched and flipped.
When initially launched, the cards are basically have no border.
Here is what the cards look like after I spam the shuffle button. The border darkens on every press:
Here are some snippets of the relevant parts of my code:
MainAcivity.java
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.shuffleButton:
pager.removeAllViews();
pagerAdapter.shuffle();
pager.setAdapter(pagerAdapter);
}
return true;
CardPagerAdapter.java
public class CardPagerAdapter extends FragmentStatePagerAdapter {
public static final String CARD = "CARD";
private static final float WIDTH_SCALE = 0.95f;
private int count;
private Deck deck;
private ArrayList<Card> cards;
private boolean isShuffled;
public CardPagerAdapter(FragmentManager fragmentManager, Deck deck) {
super(fragmentManager);
this.deck = deck;
this.count = deck.getSize();
this.cards = deck.getCards();
this.isShuffled = false;
}
#Override
public Fragment getItem(int position) {
CardContainerFragment cardContainerFragment = new
CardContainerFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(CARD, cards.get(position));
cardContainerFragment.setArguments(bundle);
return cardContainerFragment;
}
#Override
public int getItemPosition(Object item) {
return POSITION_NONE;
}
#Override
public int getCount() {
return count;
}
/**
* Override the pageWidth in order to be able
* to see other cards on the side of the current card.
* #param position The position of the current card
* #return The multiplier by which to change the width by
*/
#Override
public float getPageWidth(int position) {
return WIDTH_SCALE;
}
public void shuffle() {
if (isShuffled) {
cards = deck.getCards();
} else {
Collections.shuffle(cards);
}
isShuffled = !isShuffled;
notifyDataSetChanged();
}
}
CardContainerFragment.java
public class CardContainerFragment extends Fragment {
public static final String FLIPPED = "FLIPPED";
private static final float DISTANCE = 8000;
private CardFragment frontCardFragment;
private CardFragment backCardFragment;
private boolean cardFlipped;
public CardContainerFragment() {
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
// Create the card fragment view
final View rootView = inflater.inflate(
R.layout.card_fragment, container, false);
this.cardFlipped = false;
Bundle bundle = this.getArguments();
// Make the front and back cards
Bundle frontBundle = (Bundle) bundle.clone();
Bundle backBundle = (Bundle) bundle.clone() ;
frontCardFragment = new CardFragment();
frontBundle.putByte(FLIPPED, (byte) 0);
frontCardFragment.setArguments(frontBundle);
backCardFragment = new CardFragment();
backBundle.putByte(FLIPPED, (byte) 1);
backCardFragment.setArguments(backBundle);
// Set the first viewed fragment to be the the front of the card
getChildFragmentManager()
.beginTransaction()
.add(R.id.container, frontCardFragment)
.commit();
// Flip the card once touched
rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flipCard();
}
});
return rootView;
}
/**
* Swaps the visible fragment with the other fragment (the other side of
the card)
* Animates the transition between the change with a flip animation.
*/
public void flipCard() {
Fragment fragment;
if (cardFlipped) {
fragment = frontCardFragment;
} else {
fragment = backCardFragment;
}
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_left_in,
R.animator.card_flip_left_out,
R.animator.card_flip_right_in,
R.animator.card_flip_right_out)
.replace(R.id.container, fragment)
.commit();
cardFlipped = !cardFlipped;
}
public static class CardFragment extends Fragment {
private TextView cardText;
private ImageButton starButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Create the card fragment view and get the card object
View view = inflater.inflate(R.layout.card_view, container,
false);
Bundle bundle = this.getArguments();
final Card card = bundle.getParcelable(CardPagerAdapter.CARD);
boolean cardFlipped = bundle.getByte(FLIPPED) != 0;
// Change camera perspective to not have the flip animation be
// distorted
float scale = getResources().getDisplayMetrics().density;
view.setCameraDistance(DISTANCE * scale);
// Set the text from the card to the fragment's textview
cardText = (TextView) view.findViewById(R.id.cardText);
if (cardFlipped) {
cardText.setText(card.getBackText());
} else {
cardText.setText(card.getFrontText());
}
// Make the star button and set it based on if the card is
// starred
starButton = (ImageButton) view.findViewById(R.id.starButton);
if (card.isStarred()) {
starButton.setImageResource(R.mipmap.ic_star_white_48dp);
} else {
starButton.setImageResource(R.mipmap.ic_star_border_black_48dp);
}
starButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!card.isStarred()) {
starButton.setImageResource(R.mipmap.ic_star_white_48dp);
} else {
starButton.setImageResource(R.mipmap.ic_star_border_black_48dp);
}
card.toggleStarred();
}
});
return view;
}
}
}
Any help at all would be appreciated.
*EDIT
As requested here is the XML
card_fragment.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:stateListAnimator="#null">
</FrameLayout>
card_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_gravity="center"
android:stateListAnimator="#null">
<android.support.v7.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="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardUseCompatPadding="true"
android:stateListAnimator="#null">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/cardText"
android:layout_width="350dp"
android:layout_height="500dp"
android:gravity="center"
android:text="This is the card contents."
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent" />
<ImageButton
android:id="#+id/starButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:background="#android:color/transparent"
android:tint="#android:color/darker_gray"
app:layout_constraintRight_toRightOf="#+id/cardText"
app:layout_constraintTop_toTopOf="#+id/cardText"
app:srcCompat="#mipmap/ic_star_border_black_48dp" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="match_parent"
android:background="#d3d3d3"
tools:context="com.benvo.viewpager.activities.MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ProgressBar
android:id="#+id/deckProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>