Open Fragment OnClick on Recyclerview item from ApI - android

I am getting data from API in recycleview using AQuery but now i want to open fragment from API onclick on recyclerview item so how can i implement this.
I want to do same as Instagram app,like on home page when we click on name we get all the details of users on another fragment.

//CouponFragment.java
public class CouponFragment extends Fragment implements CouponList.OnActionCompleted{
private RecyclerView recyclerView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
recyclerView = new RecyclerView(getActivity());
return recyclerView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayList<String> coupons = new ArrayList<>();
coupons.add("Tamil");
coupons.add("English");
coupons.add("Malay");
coupons.add("Chinese");
recyclerView.setAdapter(new CouponList(coupons,CouponFragment.this));
}
#Override
public void OnClick(Coupon coupon){
//new fragment
CouponDetails couponDetails = new CouponDetails();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.home_container, couponDetails);
//R.id.home_container is your FrameLayout id
transaction.addToBackStack("couponDetails");
transaction.commit();
}
}
cardview_coupon_info.xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/tools"
android:foreground="?android:attr/selectableItemBackground"
android:transitionName="coupon_info_card"
android:id="#+id/coupon_info_card"
android:clickable="true"
android:layout_margin="#dimen/item_margin"
card_view:cardElevation="6dp"
card_view:cardCornerRadius="4dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/coupon_description"
android:gravity="start"
android:layout_margin="4dp" />
</android.support.v7.widget.CardView>
CouponList.java (Recyclerview adapter)
public class CouponList extends RecyclerView.Adapter<CouponList.ViewHolder> {
private ArrayList<String> coupons;
private OnActionCompleted callback;
public CouponList(ArrayList<String> coupons,OnActionCompleted callback)
{
this.coupons = coupons;
this.callback = callback;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_coupon_info,parent,false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.description.setText(coupons.get(position);
}
#Override
public int getItemCount() {
return coupons.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView description;
public ViewHolder(View itemView) {
super(itemView);
description = (TextView) itemView.findViewById(R.id.coupon_description);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
String coupon = coupons.get(getAdapterPosition());
callback.OnClick(coupon);
}
}
public interface OnActionCompleted {
public void OnClick(Coupon coupon);
}
}
You can use this in Activity as well for easy implementation for multiple widget clicks in recycler view item :)

Do the following in your recycler view item onClick.
FragmentManager fm = getFragmentManager();// If you're in an activity.
FragmentManager fm = getSupportFragmentManager();// If you're already inside another fragment
YourFragment yfObj = new YourFragment();
fm.beginTransaction().replace(R.id.fragmentContainer, yfObj).commit();
Here, fm is the FragmentManager object, with which only you can conduct a fragment transaction, such as loading a new fragment.
yfObj is the object of the fragment class that you want to load.
R.id.fragmentContainer is the id of the container layout you have declared in your XML file, where you want to load the fragment.
Hope this helps !

Related

Error: E/RecyclerView: No adapter attached; skipping layout on Fragments

I am trying to display a RecyclerView on a fragment using FireBase Database, but for some unknown reason its giving me this error: E/RecyclerView: No adapter attached; Im pretty sure im actually attaching the adapter, here's the code:
Main Activity
public class MainActivity extends AppCompatActivity {
Fragment currentFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null){
currentFragment = new MapsFragment();
changeFragment(currentFragment);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.menu_bookmarkList:
currentFragment = new ListaFragment();
break;
case R.id.menu_mapa:
currentFragment = new MapsFragment();
break;
}
changeFragment(currentFragment);
return super.onOptionsItemSelected(item);
}
private void changeFragment(Fragment currentFragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,currentFragment).commit();
}
}
ListaFragment (the one that should display the Recycler):
public class ListaFragment extends Fragment implements MyAdapter.RecyclerItemClick{
private MyAdapter myAdapter;
private RecyclerView recycler;
FirebaseDatabase database;
DatabaseReference myRef;
public ListaFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_lista, container, false);
database = FirebaseDatabase.getInstance();
myRef = database.getReference("Marcador");
recycler = (RecyclerView) v.findViewById(R.id.recyler);
recycler.setLayoutManager(new LinearLayoutManager(getContext()));
FirebaseRecyclerOptions<Marcador> options = new FirebaseRecyclerOptions.Builder<Marcador>()
.setQuery(myRef, Marcador.class).build();
myAdapter = new MyAdapter(options,this);
recycler.setAdapter(myAdapter);
return v;
}
#Override
public void onStart(){
super.onStart();
myAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
myAdapter.stopListening();
}
#Override
public void itemClick(Marcador marcador) {
}
}
And the adapter i've done (im skipping the xml's since they are quite simple):
public class MyAdapter extends FirebaseRecyclerAdapter<Marcador,MyAdapter.MarcadorHolder> {
private Context context;
private RecyclerItemClick itemClick;
public MyAdapter(#NonNull FirebaseRecyclerOptions<Marcador> options, RecyclerItemClick itemClick) {
super(options);
this.itemClick = itemClick;
}
#Override
protected void onBindViewHolder(#NonNull final MarcadorHolder holder, int position, #NonNull Marcador model) {
final Marcador marcador = getItem(position);
holder.textViewNom.setText(model.getNom());
holder.textViewLatitude.setText(String.valueOf(model.getLatitude()));
holder.textViewLongitude.setText(model.getLongitude());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemClick.itemClick(marcador);
}
});
}
#NonNull
#Override
public MarcadorHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recylcer_view_item,parent,false);
context = parent.getContext();
return new MarcadorHolder(v);
}
public class MarcadorHolder extends RecyclerView.ViewHolder{
TextView textViewNom;
TextView textViewLatitude;
TextView textViewLongitude;
public MarcadorHolder(#NonNull View itemView) {
super(itemView);
textViewNom = itemView.findViewById(R.id.textViewNom);
textViewLatitude = itemView.findViewById(R.id.textViewLatitud);
textViewLongitude = itemView.findViewById(R.id.textViewLongitut);
}
}
public interface RecyclerItemClick {
void itemClick(Marcador marcador);
}
}
I hope someone can give me an answer of why this is happening, since i've checked other options and i can't really get through it.
XML's attached of fragment:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.ListaFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyler"
android:layout_width="match_parent"
android:layout_height="545dp" />
</LinearLayout>
XML attached of item of recycler view:
<?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="60dp" android:background="#CDCDCD" android:layout_marginBottom="5dp"
>
<TextView
android:id="#+id/textViewNom"
android:layout_width="410dp"
android:layout_height="55dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="5dp"
android:text="Title"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/textViewLatitud"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="35dp"
android:text="latitud" />
<TextView
android:id="#+id/textViewLongitut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="125dp"
android:layout_marginTop="35dp"
android:text="longitut" />
<ImageView
android:id="#+id/imageView"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="265dp"
android:layout_marginTop="10dp"
/>
</RelativeLayout>
Do use below lines
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recycler.setLayoutManager(layoutManager);
recycler.setAdapter(adapter);
According to Fragment API Reference:
It is recommended to only inflate the layout in this method and move logic that operates on the returned View to onViewCreated(View, Bundle).
So in onCreateView you should only inflate your layout hence the View v = inflater.inflate(R.layout.fragment_lista, container, false); you used and move logic of your code to onViewCreated and the reason you facing E/RecyclerView: No adapter attached; is because you're trying to setting adapter for your recyclerview before even creation/inflation of the view which is failing to complete therefore after the creation/inflation is done there's no adapter attached to recyclerview.
It is generally recommended to not initialize the component using findViewById in onViewCreated() as per the The Google Developer Documents.
You should inflate your layout in onCreateView but shouldn't
initialize other views using findViewById in onCreateView.
Because in this method not every View is not Properly initialized. So, prefer to use onViewCreated() to get your view's Id and do setUp the UI.

Items in RecyclerView in a Fragmnet don't appear

I saw there are similar post but my code is the same as the codes in the solutions so they weren't useful in my case. My app starts but and two tabs are shown. However the one that is supposed to show the items from a RecyclerView that's in it is empty.I also get this error:
E/RecyclerView: No adapter attached; skipping layout
So I have an Activity with a TabLayout and a ViewPager
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
PagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout=findViewById(R.id.tab_layout);
viewPager=findViewById(R.id.view_pager);
tabLayout.addTab(tabLayout.newTab().setText("CitiesFragment"));
tabLayout.addTab(tabLayout.newTab().setText("My CitiesFragment"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
pagerAdapter=new PagerAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
This is a fragment with only a RecyclerView in it
public class CitiesFragment extends Fragment {
RecyclerView recyclerView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View itemView = inflater.inflate(R.layout.cities_layout, container, false);
recyclerView = itemView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
List<City> data = Database.getDatabase();
CitiesAdapter adapter = new CitiesAdapter(data);
recyclerView.setAdapter(adapter);
return itemView;
}
}
This is the XML for the fragment
<?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="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
And this is the Adapter
public class CitiesAdapter extends RecyclerView.Adapter<CitiesVIewHolder> {
List<City> data;
private int itemCount;
public CitiesAdapter(List<City> data) {
this.data = data;
itemCount=data.size();
}
#NonNull
#Override
public CitiesVIewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.city_layout, viewGroup, false);
CitiesVIewHolder viewHolder = new CitiesVIewHolder(itemView);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull CitiesVIewHolder citiesVIewHolder, int position) {
City city = data.get(position);
citiesVIewHolder.txtCityName.setText(city.getCityName());
citiesVIewHolder.txtCityInfo.setText(city.getCityInfo());
LoadImageTask loadImageTask = new LoadImageTask(citiesVIewHolder.imgCity);
loadImageTask.execute(city.getImageUrl());
}
#Override
public int getItemCount() {
return itemCount;
}
}
And the XML for the Adapter
<?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="vertical">
<ImageView
android:id="#+id/img_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txt_city_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txt_city_info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
My PagerAdapter only returns one of the two fragments(one of them is currently empty and the other on is with the RecyclerView)
public class PagerAdapter extends FragmentStatePagerAdapter {
private int itemCount;
public PagerAdapter(FragmentManager fm, int itemCount) {
super(fm);
this.itemCount = itemCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new CitiesFragment();
case 1:
return new MyCitiesFragment();
default:
return null;
}
}
#Override
public int getCount() {
return itemCount;
}
}
I am sorry for the code overload but I really can not understand what I'm doing wrong. Thanks for the help in advance.
First of all your adapter xml root LinearLayout has height set to match_parent so change that to wrap_content.
Second one override onViewCreated and there set recyclerView not in onCreateView. For example:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setHasFixedSize(true);
List<City> data = Database.getDatabase();
CitiesAdapter adapter = new CitiesAdapter(data);
recyclerView.setAdapter(adapter);
}
Also consider adding line: recyclerView.setHasFixedSize(true);
E/RecyclerView: No adapter attached; skipping layout
TabLayout display fragment with recyclerView but fragment takes more time to load datasource that makes recycler created without adapter attached.
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View itemView = inflater.inflate(R.layout.cities_layout, container, false);
recyclerView = itemView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// List<City> data = Database.getDatabase(); // Don't fetch data on Main (UI) Thread
CitiesAdapter adapter = new CitiesAdapter(new ArrayList<City>()); //
recyclerView.setAdapter(adapter);
// Display city here one background and then update adapter.
return itemView;
}
If Datasource fetch data from local database then you can just use handler or postDelay on RecyclerView
recyclerView.postDelay(new Runnable(){
public void run(){
adapter.setCityList(result);
}
},500);
If you load data for server datasource the use background task, You can check this answer for fetch data from server with smooth way.
// load datasource inside Async Task.
new AsyncTaskHandler(new OnFinishCallback() {
#Override
public void onSuccess(List<City> result) {
adapter.setCityList(result);
}
}).execute("param that need to load datasource");
I have create a simple app to simulate your case.
RecyclerView width must be match_partent
<!--RecyclerView width must be match_parent-->
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
You can find the complete sample/CityPreview app on Github

RecyclerView won't display my database content

I have a database of Users and I'm trying to use a RecyclerView to display every User entry I have. From my logs, I can tell that my RecyclerView isn't even being interacted with. Here is the class where I call it:
public class WelcomePage extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome_page);
FragmentManager manager = getFragmentManager();
RecyclerFragment mRecyclerFragment = new RecyclerFragment();
if(mRecyclerFragment == null) {
manager.beginTransaction()
.add(R.id.recycler, mRecyclerFragment)
.commit();
}
}
}
This is my holder class:
public class RecyclerHolder extends RecyclerView.ViewHolder{
private static final String TAG = "RecyclerHolder";
private TextView mFullName;
private TextView mBirthDate;
private TextView mHomeTown;
private TextView mBio;
User mUser;
RecyclerHolder(View itemView){
super(itemView);
mFullName = (TextView)itemView.findViewById(R.id.text_view_name);
mBirthDate = (TextView)itemView.findViewById(R.id.text_view_birthday);
mHomeTown = (TextView)itemView.findViewById(R.id.text_view_hometown);
mBio = (TextView)itemView.findViewById(R.id.text_view_bio);
public void bind(User user) {
mUser = user;
mFullName.setText(user.getFullName());
mBirthDate.setText(user.getBirthDate().toString());
mHomeTown.setText(user.getHomeTown());
mBio.setText(user.getBio());
}
}
Here's my adapter class:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerHolder> {
private ArrayList<User> mUsers;
public RecyclerAdapter(ArrayList<User> user) {
mUsers = user;
}
#Override
public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.view_recycler, parent, false);
RecyclerHolder holder = new RecyclerHolder(view);
return holder;
}
#Override
public void onBindViewHolder(RecyclerHolder holder, int position){
holder.bind(mUsers.get(position));
}
#Override
public int getItemCount() {
return mUsers.size();
}
}
Here's my fragment class:
public class RecyclerFragment extends Fragment {
private RecyclerView mRecyclerView;
DBCursorWrapper db;
public RecyclerFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler, container, false);
mRecyclerView = (RecyclerView)view.findViewById(R.id.recycler);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerAdapter adapter = new RecyclerAdapter(db.getUserList());
mRecyclerView.setAdapter(adapter);
return view;
}
}
Here is the XML for my holder:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/view_recycler">
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
/>
</LinearLayout>
Here is my XML for my fragment:
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.csc214.just4kas.project02.RecyclerFragment">
</android.support.v7.widget.RecyclerView>
Here is my XML for where I call my RecyclerView:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame_layout_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.csc214.just4kas.project02.WelcomePage">
</FrameLayout>
The getUserList() has been tested individually and works perfectly!
Any help would be super appreciated! I just want a RecyclerView of all the contents in my database!! Thanks!
I think you may be using the wrong layout when you replace add it to the main activity. try (R.id.frame_layout_recycler_view) instead or R.id.recycler.
Or there might be a issue when use the database in this context.

Layout for tablets using two fragments

I am doing a sample project as an excercise and want to display two fragments in the same activity when dealing with tablets(7' and 10').
So what I have so far is this.
As you can see I can display the data of my recyclerview in the left (static) fragment. However the right fragment is empty.
So I have two questions.
1) How to display by default in the right fragment the data of the first row of recyclerview?(ie image and article)
2) How to implement the click listener and update the right fragment?
Here is my code:
MainActivity
public class MainActivity extends AppCompatActivity {
private boolean mTwoPane;
private static final String DETAIL_FRAGMENT_TAG = "DFTAG";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(findViewById(R.id.detailed_match_reports)!=null) {
mTwoPane = true;
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.detailed_match_reports, new DetailedActivityFragment(),DETAIL_FRAGMENT_TAG)
.commit();
}else{
mTwoPane = false;
}
}
}
}
layout/activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/match_reports"
android:name="theo.testing.androidservices.fragments.MainActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context="theo.testing.androidservices.activities.MainActivity"
tools:layout="#android:layout/list_content" />
layout-sw600dp/activity_main
<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:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
tools:context="theo.testing.androidservices.activities.MainActivity">
<fragment
android:id="#+id/match_reports"
android:name="theo.testing.androidservices.fragments.MainActivityFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
tools:layout="#android:layout/list_content" />
<FrameLayout
android:id="#+id/detailed_match_reports"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4" />
</LinearLayout>
MainActivityFragment
public class MainActivityFragment extends Fragment {
public static final String TAG = "AelApp";
public static ArrayList<MyModel> listItemsList;
RecyclerView myList;
public static MatchReportsAdapter adapter;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateMatchReport();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
getActivity().setTitle("Match Report");
View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false);
listItemsList = new ArrayList<>();
myList = (RecyclerView)rootView.findViewById(R.id.listview_match_reports);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
myList.setHasFixedSize(true);
myList.setLayoutManager(linearLayoutManager);
adapter = new MatchReportsAdapter(getActivity(), listItemsList);
myList.setAdapter(adapter);
return rootView;
}
public void updateMatchReport(){
Intent i = new Intent(getActivity(), MatchReport.class);
getActivity().startService(i);
}
}
First let me answer the second question. To show a fragment on the right side of the screen add something like this (note how I'm using that id of the frame layout to replace the fragment):
Fragment fragment = new MyRightSideFragment();
FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.detailed_match_reports, fragment).commit();
Now, for the first question, you need to implement click listener, you can find an example here.
public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
showDetail(position);
}
});
}
}
Notice that I'm using the tag of the view to identify the position (so somwhere in your onBindViewHolder code you must set this tag).
public function showDetail(int position) {
... show fragment por position
}
and finally, when your in your OnCreateView or somewhere in your setup code, call showDetail(0).

"Recycler View..No adapter attached: skipping layout" error using Async Task in a fragment

public class ReferralStatus extends Fragment {
public MyPendingAdapter pAdapter;
public RecyclerView recyclerView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View layout= inflater.inflate(R.layout.fragment_referral_status, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.pendingRecyclerList);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return layout;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
PendingAsyncTask pendingRunner = new PendingAsyncTask();
pendingRunner.execute("someURL");
}
public class MyPendingAdapter extends RecyclerView.Adapter<MyPendingAdapter.PendingUserHolder> {
Context context;
String[] pendingUserArray, socialSitesArray;
public MyPendingAdapter(Context c, String[] pendingUserList, String[] socialSites) {
Log.d("golu", "pendingConstructor");
this.context=c;
this.pendingUserArray=pendingUserList;
this.socialSitesArray=socialSites;
}
public class PendingUserHolder extends RecyclerView.ViewHolder{
TextView pendingUsername;
TextView socialSite;
public PendingUserHolder(View v){
super(v);
pendingUsername = (TextView) v.findViewById(R.id.pendingUsername);
socialSite= (TextView) v.findViewById(R.id.socialSiteLabel);
}
}
#Override
public PendingUserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d("golu", "pendingHolder");
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.pending_list_row,parent,false);
PendingUserHolder holder = new PendingUserHolder(row);
return holder;
}
#Override
public void onBindViewHolder(PendingUserHolder holder, int position) {
holder.pendingUsername.setText(pendingUserArray[position]);
holder.socialSite.setText(socialSitesArray[position]);
}
#Override
public int getItemCount() {
Log.d("golu", "pendingCount");
return pendingUserArray.length;
}
}
public class PendingAsyncTask extends AsyncTask<String,Void,Boolean>{
String [] pendingUserList, socialSitesMedium;
#Override
protected Boolean doInBackground(String... params) {
//just returning simple boolean value
return true;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if(aBoolean)
{
//Hardcoding Arrays for now
pendingUserList=getResources().getStringArray(R.array.pendingUserList);
socialSitesMedium=getResources().getStringArray(R.array.socialSites);
pAdapter = new MyPendingAdapter(getActivity(),pendingUserList,socialSitesMedium);
recyclerView.setAdapter(pAdapter);
}
}
}
//Here is the XML file
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/pending"
android:id="#+id/pendingLabel"
android:textColor="#FF0000"
android:textAllCaps="true"
android:textStyle="bold"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:layout_marginLeft="10dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/pendingRecyclerList"
android:layout_width = "match_parent"
android:layout_height = "match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
//Its showing the Skipping layout error ....What am I doing wrong?
//FYI: I tried initialising RecyclerView and setting the LinearLayoutManager in onPostExecute....it still didnt work :/
The problem lies in OnCreateView method
You need to initialise the adapter there and set the adapter to the recycler view.
As the adapter will pass no data you can update the display later.
As the onCreateView Method is the method which updates the display,so its important to initialise it else it will give an error "no adapter attached skipping display"
What am I doing wrong?
RecyclerView (and also ListView) requires Adapter to be able to work, because adapter is the way these widgets gets the data to display from. You have adapter in your code but you lack the code that tells RecyclerView to use it: setAdapter().
See https://developer.android.com/training/material/lists-cards.html for more details

Categories

Resources