Master/Detail layout not rendering - android

I'm trying to make an app that fetches a book list from an API and displays it on the master list and, upon clicking, it displays the details. It works fine with mobiles, but I can't get it to work with tablets and since there's no error I can't find out where I went wrong.
On tablets it renders as if on a phone instead of rendering the two pane view.
I'm using a single activity with fragments.
"Main" activity:
public class ItemListActivity extends AppCompatActivity {
public static FragmentManager fragmentManager;
private boolean isTwoPane = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
determinePaneLayout();
fragmentManager = getSupportFragmentManager();
if(isTwoPane){
//fragmentManager.beginTransaction().add(R.id.master_dual, new ItemsListFragment()).commit();
fragmentManager.beginTransaction().add(R.id.flDetailContainer, new ItemDetailFragment()).commit();
fragmentManager.beginTransaction().add(R.id.fragmentContainer, new ItemsListFragment()).commit();
} else {
fragmentManager.beginTransaction().add(R.id.fragmentContainer, new ItemsListFragment()).commit();
}
}
private void determinePaneLayout() {
FrameLayout fragmentItemDetail = (FrameLayout) findViewById(R.id.flDetailContainer);
// If there is a second pane for details
if (fragmentItemDetail != null) {
isTwoPane = true;
}
}
Item List Fragment:
public class ItemsListFragment extends Fragment {
private ArrayList<Book> bookList;
private ArrayList<String> bookNames;
private ArrayAdapter<Book> bookArrayAdapter;
private ArrayAdapter<String> bookNamesAdapter;
private ApiInterface apiInterface;
private ListView lvItems;
private static final String bookKey = "newBook";
private static Book nBook;
public ItemsListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_items_list,
container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
lvItems = view.findViewById(R.id.lvItems);
bookNames = new ArrayList<>();
//bookNames.add(0, "Gabriel");
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<ArrayList<Book>> call = apiInterface.getBooks();
call.enqueue(new Callback<ArrayList<Book>>() {
#Override
public void onResponse(Call<ArrayList<Book>> call, Response<ArrayList<Book>> response) {
bookList = new ArrayList<>();
bookList = response.body();
bookArrayAdapter = new ArrayAdapter<>(getContext(),
android.R.layout.simple_list_item_activated_1, bookList);
lvItems.setAdapter(bookArrayAdapter);
}
#Override
public void onFailure(Call<ArrayList<Book>> call, Throwable t) {
}
});
lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
nBook = bookList.get(i);
if(view.findViewById(R.id.flDetailContainer) != null){
ItemListActivity.fragmentManager.beginTransaction().replace(R.id.flDetailContainer, ItemDetailFragment.newInstance(nBook)).addToBackStack(null).commit();
} else {
ItemListActivity.fragmentManager.beginTransaction().replace(R.id.fragmentContainer, ItemDetailFragment.newInstance(nBook)).addToBackStack(null).commit();
}
}
});
}`
Item Detail Fragment:
public class ItemDetailFragment extends Fragment {
private static final String bookKey = "newBook";
private static Book nBook;
private TextView title;
private TextView isbn;
private TextView currency;
private TextView price;
private TextView author;
public static ItemDetailFragment newInstance(Book book) {
ItemDetailFragment fragment = new ItemDetailFragment();
Bundle args = new Bundle();
args.putSerializable(bookKey, book);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
nBook = (Book)getArguments().getSerializable(bookKey);
Log.v("BundleOK", "BundleOK");
} else {
Log.v("Bundle Nulo", "Bundle nulo");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate view
View view = inflater.inflate(R.layout.fragment_item_detail,
container, false);
// Return view
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
title = view.findViewById(R.id.tvTitle);
isbn = view.findViewById(R.id.tvIsbn);
currency = view.findViewById(R.id.tvCurrency);
price = view.findViewById(R.id.tvPrice);
author = view.findViewById(R.id.tvAuthor);
title.setText(nBook.getTitle());
isbn.setText("ISBN: " + nBook.getIsbn());
currency.setText("Currency: "+ nBook.getCurrency());
price.setText("Price: "+ String.valueOf((long)nBook.getPrice()/100));
author.setText("Autor: "+nBook.getAuthor());
}
XML for dual pane:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:showDividers="middle"
android:baselineAligned="false"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/fragmentItemsList"
android:name="gabrielgomes.studio.com.itemretrieve.ItemsListFragment"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
tools:layout="#layout/fragment_items_list" />
<View android:background="#000000"
android:layout_width="1dp"
android:layout_height="wrap_content"
/>
<FrameLayout
android:id="#+id/flDetailContainer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
XML for the Main Activity (Item List Activity)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
XML for the Item Detail Fragment:
<?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="match_parent" >
<TextView
android:id="#+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="110dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:fontFamily="#font/baskervillebt"
android:gravity="center"
android:text="Item Title"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/tvIsbn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tvTitle"
android:layout_centerHorizontal="true"
android:layout_marginTop="44dp"
android:fontFamily="#font/baskervilleitalicbt"
android:text="Item Body"
android:textSize="16sp" />
<TextView
android:id="#+id/tvPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tvIsbn"
android:layout_centerHorizontal="true"
android:layout_marginTop="47dp"
android:fontFamily="#font/baskervilleitalicbt"
android:text="Price"
android:textSize="16sp" />
<TextView
android:id="#+id/tvCurrency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tvPrice"
android:layout_centerHorizontal="true"
android:fontFamily="#font/baskervilleitalicbt"
android:layout_marginTop="44dp"
android:text="Currency"
android:textSize="16sp" />
<TextView
android:id="#+id/tvAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tvCurrency"
android:fontFamily="#font/baskervilleitalicbt"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp"
android:text="Author"
android:textSize="16sp" />
</RelativeLayout>
I've been cracking my head for 5 days now, so any help is really appreciated! I tried a number of tutorials and searched SO thoroughly but no go!
Cheers!

I believe you have two copies activity_item_list.xml layout file and one is res/layout/ folder and another one is in res/layout-sw600dp/ folder.
sw600dp --> Screen width above 600dp use this layout else if less than 600dp use default layout file.
And also you make sure keep same attribute ids same in both the layout files.

Related

How can I create List with dynamically number of items with Android Studio

I created list using example: Material design suggestions for lists with avatar, text and icon
I want to have list with upcoming movies, so I need list with dynamically number of items. I dont understand and I dont know how I should do it.
There is my code for one item list:
public class FragmentOne extends Fragment {
TextView textView;
TextView textView2;
ImageView imageView;
public static FragmentOne newInstance() {
FragmentOne fragment = new FragmentOne();
return fragment;
}
public class MovieTask extends AsyncTask<Void, Void, MovieDb>{
#Override
protected MovieDb doInBackground(Void... voids) {
TmdbMovies movies = new TmdbApi("my_api_key").getMovies();
MovieDb movie = movies.getMovie(5335, "en");
return movie;
}
#Override
protected void onPostExecute(MovieDb movieDb) {
textView.setText(movieDb.getOriginalTitle());
textView2.setText(movieDb.getReleaseDate());
Glide.with(imageView).load("https://image.tmdb.org/t/p/w500" + movieDb.getPosterPath()).into(imageView);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
MovieTask mt = new MovieTask();
mt.execute();
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View returnView = inflater.inflate(R.layout.fragment_one, container, false);
textView = (TextView) returnView.findViewById(R.id.text);
textView2 = (TextView) returnView.findViewById(R.id.text2);
imageView = (ImageView) returnView.findViewById(R.id.list_icon);
return returnView;
}
}
and xml for that class
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="72dp"
tools:context=".FragmentOne">
<ImageView
android:id="#+id/list_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="16dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/list_icon"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true">
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingRight="16dp" />
<TextView
android:id="#+id/text2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingRight="16dp" />
</LinearLayout>
</RelativeLayout>
I would personally suggest you to use Recyclerview and cardview to get this job done. You will need to create an adapter class for Recyclerview if you are not familiar with this.
Just check out this link -
https://www.journaldev.com/10024/android-recyclerview-android-cardview-example-tutorial

Shared element back transition not working with recyclerview and cardviews in fragments

I'm trying to create a transition between a recycler view with cardviews fragment to a fragment that only contains 1 card. The problem is that the back transition is not working, while the enter transition is. If I remove setReorderingAllowed(true); then the back transition is working, but the enter transition stops working.
This is what I have.
Fragment with recyclerview with cardviews
public class OrdersFragment extends Fragment implements OrderAdapter.OnOrderListener {
private OrderAdapter mAdapter;
private TextView bonnenTextView;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postponeEnterTransition();
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bonnen, container, false);
bonnenTextView = view.findViewById(R.id.bonnen_text_view);
RecyclerView orderRecyclerView = view.findViewById(R.id.order_recycler_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
orderRecyclerView.setLayoutManager(layoutManager);
if (mAdapter == null) {
mAdapter = new OrderAdapter(this);
fetchOrders();
}
orderRecyclerView.setAdapter(mAdapter);
return view;
}
private void fetchOrders() {
new OrderFetcher().fetch(new Callback() {
#Override
public void onComplete(Result result) {
if (result instanceof Result.Success) {
mAdapter.setOrders((Order[]) ((Result.Success<?>)result).data);
mAdapter.notifyDataSetChanged();
} else {
Toast.makeText(getContext(), "Could not load orders", Toast.LENGTH_SHORT).show();
}
startPostponedEnterTransition();
}
});
}
#Override
public void onOrderClick(int position, View view, Order order) {
Log.i("OrderClick", "Transition name " + view.getTransitionName());
View carrierTextView = view.findViewById(R.id.carrier_text_view);
View numberTextView = view.findViewById(R.id.id_text_view);
View pickerTextView = view.findViewById(R.id.picker_text_view);
View locationTextView = view.findViewById(R.id.location_text_view);
FragmentTransaction transaction = getParentFragmentManager().beginTransaction();
transaction.addSharedElement(view, view.getTransitionName());
transaction.addSharedElement(carrierTextView, carrierTextView.getTransitionName());
transaction.addSharedElement(numberTextView, numberTextView.getTransitionName());
transaction.addSharedElement(pickerTextView, pickerTextView.getTransitionName());
transaction.addSharedElement(locationTextView, locationTextView.getTransitionName());
transaction.addSharedElement(bonnenTextView, bonnenTextView.getTransitionName());
transaction.replace(R.id.nav_host_fragment, BonFragment.newInstance(view.getTransitionName(), order));
transaction.addToBackStack(null);
transaction.setReorderingAllowed(true);
transaction.commit();
}
}
xml that goes with fragment above
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.orders.OrdersFragment">
<TextView
android:id="#+id/bonnen_text_view"
android:transitionName="bonnen_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:text="#string/orders"
android:textColor="#color/secondary"
android:textSize="40sp"
android:textStyle="bold"
android:typeface="normal" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/order_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"/>
</LinearLayout>
Fragment with single cardview
public static BonFragment newInstance(String cardTransitionName, Order order) {
BonFragment bonFragment = new BonFragment();
Bundle args = new Bundle();
args.putParcelable("orderParcel", order);
args.putString("cardTransitionName", cardTransitionName);
bonFragment.setArguments(args);
return bonFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.fragment_bon, container, false);
CardView orderCard = root.findViewById(R.id.order_card);
TextView carrierTextView = root.findViewById(R.id.carrier_text_view);
TextView numberTextView = root.findViewById(R.id.id_text_view);
TextView pickerTextView = root.findViewById(R.id.picker_text_view);
TextView locationTextView = root.findViewById(R.id.location_text_view);
if (getArguments() != null && getArguments().getParcelable("orderParcel") != null) {
Order order = getArguments().getParcelable("orderParcel");
orderCard.setTransitionName(getArguments().getString("cardTransitionName"));
if (order != null) {
carrierTextView.setTransitionName("carrier" + order.getIndex());
carrierTextView.setText(order.getCarrier());
numberTextView.setTransitionName("number" + order.getIndex());
numberTextView.setText(String.valueOf(order.getNumber()));
pickerTextView.setTransitionName("picker" + order.getIndex());
pickerTextView.setText(order.getPicker());
locationTextView.setTransitionName("location" + order.getIndex());
locationTextView.setText(order.getPosition());
carrierTextView.setText("Lorem Ipsum");
numberTextView.setText("Dolor sit amet");
pickerTextView.setText("consectetur adipiscing elit");
locationTextView.setText("Mauris semper");
}
}
orderCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getParentFragmentManager().popBackStack();
}
});
Transition transition = TransitionInflater.from(getContext()).inflateTransition(R.transition.card_transition);
setSharedElementEnterTransition(transition);
setSharedElementReturnTransition(transition);
return root;
}
xml that goes with fragment above
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.orders.OrdersFragment">
<TextView
android:transitionName="bonnen_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:text="#string/orders"
android:textColor="#color/secondary"
android:textSize="40sp"
android:textStyle="bold"
android:typeface="normal" />
<androidx.cardview.widget.CardView
android:id="#+id/order_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="#color/primaryLight"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:layout_margin="25dp">
<LinearLayout
android:transitionName="order_card_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp">
<TextView
android:id="#+id/carrier_text_view"
android:transitionName="carrier_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/secondary"
android:textSize="20sp"
android:textStyle="bold"/>
<TextView
android:id="#+id/id_text_view"
android:transitionName="id_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/secondary" />
<TextView
android:id="#+id/picker_text_view"
android:transitionName="picker_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/secondary" />
<TextView
android:id="#+id/location_text_view"
android:transitionName="location_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/secondary" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
This is what it looks like with setReorderingAllowed(true);
This is what it looks like without setReorderingAllowed(true);
EDIT
After applying the answer given by ianhanniballake I got it working.
Here is what I did for future reference.
The only changes I made is in the OrdersFragment class.
I removed the override of the onCreate() method.
I removed the startPostponedEnterTransition(); from my fetchOrders() method and I added
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
postponeEnterTransition();
final ViewGroup parentView = (ViewGroup) view.getParent();
parentView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
parentView.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return true;
}
});
super.onViewCreated(view, savedInstanceState);
}
That's it
As per the Use shared element transitions with a RecyclerView guide, you're calling startPostponedEnterTransition() too early - after setting your data (and calling notifyDataSetChanged() to inform the adapter), you need to wait until the RecyclerView is actually measured and laid out. This requires that you add an OnPreDrawListener and only call startPostponedEnterTransition() once that fires.
In Kotlin you need to start the transition in doOnPreDraw callback of the recyclerView like below:
recyclerView.doOnPreDraw {
startPostponedEnterTransition()
}

RecyclerView items inside BottomSheetDialogFragment need double touch after fast scrolling

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

ListView onItemClickListener not working within fragment

I know there is a few dozens of these posts, however even after hours of searching and trying different solutions I have not been able to make my list view work.
The ListView is within a fragment, which also contaains a TextView, and is the reason it is not a ListFragment. This fragment is within an Activity that contains the Fragment as a Framelayout and a Button.
The ListView is getting populated with data, but clicking on one of these items nothing happens.
Activity
public class TurnOnHeadbandActivity extends AppCompatActivity {
private MuseManagerAndroid manager = null;
private final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.turn_on_headband_activity);
// XX this must come before other libmuse API calls; it loads the
// library.
manager = MuseManagerAndroid.getInstance();
manager.setContext(this);
manager.startListening();
handler.post(tickUi);
}
private final Runnable tickUi = new Runnable() {
#Override
public void run() {
List<Muse> pairedMuses = manager.getMuses();
if (pairedMuses.size() >= 1) {
Fragment connectedFragment = new TurnOnHeadbandConnectedFragment();
PairedMuses pairedMusesObject = new PairedMuses(pairedMuses);
Bundle args = new Bundle();
args.putSerializable("pairedMuses", pairedMusesObject);
connectedFragment.setArguments(args);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.turnOnFragment, connectedFragment);
fragmentTransaction.commit();
}
handler.postDelayed(tickUi, 1000 / 60);
}
};
}
XML for Activity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/nightsky">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="2">
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:id="#+id/turnOnFragment"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3">
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/faqbutton"
android:layout_margin="10dp"
android:textColor="#color/textColor"
android:text="FAQ"/>
</LinearLayout>
Fragment
public class TurnOnHeadbandConnectedFragment extends Fragment implements OnItemClickListener {
private ListView museListView;
public TurnOnHeadbandConnectedFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.turn_on_headband_connected_fragment, container, false);
Bundle bundle = getArguments();
PairedMuses pairedMuses = (PairedMuses)bundle.getSerializable("pairedMuses");
// Fetch the names and MacAddresses of connected muses and store them in string array
int musesAmount = pairedMuses.getPairedMuses().size();
String[] musesMacAddresses = new String[musesAmount];
for (int i = 0; i < musesAmount; i++) {
musesMacAddresses[i] = String.valueOf(pairedMuses.getPairedMuses().get(i).getName().concat(pairedMuses.getPairedMuses().get(i).getMacAddress()));
}
museListView = (ListView) rootView.findViewById(R.id.museListView);
ArrayAdapter<String> listViewAdapter = new ArrayAdapter<>(getActivity(), R.layout.listview_item, musesMacAddresses);
museListView.setAdapter(listViewAdapter);
museListView.setOnItemClickListener(this);
return rootView;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getActivity(), Activity.class);
intent.putExtra("id", id);
startActivity(intent);
}
}
XML for Fragment
<LinearLayout 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"
android:orientation="vertical"
android:layout_margin="10dp"
tools:context="com.musesleep.musesleep.TurnOnHeadbandConnectedFragment"
android:descendantFocusability="blocksDescendants">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:gravity="center"
android:textColor="#color/textColor"
android:text="Select your headband from the list:"/>
<ListView
android:id="#+id/museListView"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
XML for custom ListView Item
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:padding="5dp"
android:background="#40D3D3D3"
android:gravity="center_vertical"
android:textColor="#color/textColor"/>

UI appearance changed after switching from activity to fragment

I had an activity with a Listview containing text and green squares. I finally changed my mind and modified my code to use a fragment instead of an activity. But then my text color changed and I can't see the green squares anymore. I didn't changed anything in my list code or the color of the text so I don't understand what's happening.
Thank you for your help.
MainActivity is only used as a fragment container :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.ll_container);
if (fragment == null) {
fragment = new PollutionLevelsFragment();
fm.beginTransaction()
.add(R.id.ll_container, fragment)
.commit();
}
}
}
MainActivity layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The fragment class
public class PollutionLevelsFragment extends Fragment implements PollutionLevelsFragmentMVP.View {
private PollutionLevelAdapter plAdapter;
#BindString(R.string.city)
String city;
#BindString(R.string.aqicn_token)
String authToken;
#BindView(R.id.lv_pollution_levels)
ListView lvPollutionLevels;
#Inject
PollutionLevelsFragmentMVP.Presenter presenter;
private ViewModel pollutionData;
private ArrayList<String> testbidon;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pollution_levels, container, false);
ButterKnife.bind(this,view);
// Construct the data source
ArrayList<PollutionLevel> arrayOfPollutionLevel = new ArrayList<>();
// Create the adapter to convert the array to views
plAdapter = new PollutionLevelAdapter(getActivity().getApplicationContext(), arrayOfPollutionLevel);
lvPollutionLevels.setAdapter(plAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
presenter.setView(this);
presenter.loadData(city, authToken);
}
#Override
public void onStop() {
super.onStop();
presenter.rxUnsubscribe();
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((App) getActivity().getApplication()).getComponent().inject(this);
}
#Override
public void updateData(ViewModel viewModel) {
this.pollutionData = viewModel;
ArrayList<PollutionLevel> pollutionLevels = viewModel.getAllPolluants();
for(PollutionLevel pl : pollutionLevels) {
plAdapter.add(pl);
}
}
}
The fragment layout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="#+id/lv_pollution_levels"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
The ArrayAdapter for the ListView
public class PollutionLevelAdapter extends ArrayAdapter<PollutionLevel> {
#BindView(R.id.tv_name)
TextView tvName;
#BindView(R.id.tv_value)
TextView tvValue;
public PollutionLevelAdapter(Context context, ArrayList<PollutionLevel> pollutionLevels) {
super(context,0,pollutionLevels);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_pollution, parent, false);
}
View view = convertView;
ButterKnife.bind(this,view);
PollutionLevel pollutionLevel = getItem(position);
tvName.setText(pollutionLevel.getName());
tvValue.setText(pollutionLevel.getValue());
return view;
}
}
My list item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_warning"
android:layout_width="20dp"
android:layout_height="20dp"
app:srcCompat="#drawable/rectangle"/>
<TextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"/>
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"/>
This is the code of the layout the Activity class that rendered the Listview correctly (so before I switched from an activity to a fragment). I didn't put the code of the Listview adapter here since it didn't change :
Activity
public class PollutionLevelsActivity extends AppCompatActivity implements PollutionLevelsActivityMVP.View {
private PollutionLevelAdapter plAdapter;
#BindString(R.string.city)
String city;
#BindString(R.string.aqicn_token)
String authToken;
#BindView(R.id.lv_pollution_levels)
ListView lvPollutionLevels;
#Inject
PollutionLevelsActivityMVP.Presenter presenter;
private ViewModel pollutionData;
private ArrayList<String> testbidon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getComponent().inject(this);
ButterKnife.bind(this);
// Construct the data source
ArrayList<PollutionLevel> arrayOfPollutionLevel = new ArrayList<>();
// Create the adapter to convert the array to views
plAdapter = new PollutionLevelAdapter(this, arrayOfPollutionLevel);
lvPollutionLevels.setAdapter(plAdapter);
}
#Override
protected void onStart() {
super.onStart();
presenter.setView(this);
presenter.loadData(city, authToken);
}
#Override
protected void onDestroy() {
super.onDestroy();
presenter.rxUnsubscribe();
}
#Override
public void updateData(ViewModel viewModel) {
this.pollutionData = viewModel;
ArrayList<PollutionLevel> pollutionLevels = viewModel.getAllPolluants();
for(PollutionLevel pl : pollutionLevels) {
plAdapter.add(pl);
}
}
}
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="com.livos.citypollution.pollutionlevels.PollutionLevelsActivity">
<ListView
android:id="#+id/lv_pollution_levels"
android:layout_width="368dp"
android:layout_height="495dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
To change Text Color add this
android:textColor="Your Color Code"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_warning"
android:layout_width="20dp"
android:layout_height="20dp"
**app:src="#drawable/rectangle"**/>
<TextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"
android:textColor="Your Color Code"/>
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"
android:textColor="Your Color Code"/>
As i am getting. You give an adapter like:
public class PollutionLevelAdapter extends ArrayAdapter<PollutionLevel> {
#BindView(R.id.tv_name)
TextView tvName;
#BindView(R.id.tv_value)
TextView tvValue;
public PollutionLevelAdapter(Context context, ArrayList<PollutionLevel> pollutionLevels) {
super(context,0,pollutionLevels);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_pollution, parent, false);
}
View view = convertView;
ButterKnife.bind(this,view);
PollutionLevel pollutionLevel = getItem(position);
tvName.setText(pollutionLevel.getName());
tvValue.setText(pollutionLevel.getValue());
return view;
}
}
You are binding your two TextView not Your ImageView as you gave your list_item_pollution, which is having ImageView so bind your ImageView like:
#BindView(R.id.iv_warning)
ImageView iv_warning;
and in getView method set is as :
iv_warning.setBackgroundColor(Color.parseColor("your color code"));

Categories

Resources