I'm learning RecyclerView and having trouble with my recycler:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/bootik_recycler"
/>
And the class:
public class BotikFragment extends Fragment {
private RecyclerView recyclerView;
private View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.recycler_botik,container);
return view;
recyclerView=(RecyclerView)view.findViewById(R.id.bootik_recycler);
I'm getting an Unreachable Statement error.
Just put the last two statements in different order:
recyclerView=(RecyclerView)view.findViewById(R.id.bootik_recycler);
return view;
Related
My app was working completely fine , when I just had the recyclerview
in fragment's xml , but I need to wrap it in constraintlayout for
some reason but my app starts crashing after that.
error message :
*java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.*
Fragment code
public class AdminPostFragment extends Fragment {
RecyclerView recyclerView;
DatabaseReference database;
MyAdapter myAdapter;
ArrayList<Updates> list;
private FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
#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 view = inflater.inflate(R.layout.fragment_admin_post, container, false);
recyclerView = view.findViewById(R.id.updates_recycler);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
if (FirebaseAuth.getInstance().getCurrentUser() != null) {
FirebaseRecyclerOptions<Updates> options =
new FirebaseRecyclerOptions.Builder<Updates>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("updates"), Updates.class)
.build();
myAdapter = new MyAdapter(options);
recyclerView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
return recyclerView;
}
Fragment XML file
<?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"
android:id="#+id/parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/updates_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
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"
app:layout_constraintVertical_bias="1.0">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
My Adapter code
package com.project.adminapp.adapter;
import java.util.ArrayList;
.....
public class MyAdapter extends FirebaseRecyclerAdapter< Updates ,MyAdapter.MyViewHolder> {
public MyAdapter(#NonNull FirebaseRecyclerOptions<Updates> options)
{
super(options);
}
#Override
protected void onBindViewHolder(#NonNull final MyViewHolder holder, final int position, #NonNull final Updates model) {
holder.updates_text.setText(model.getUpdate());
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.updates,parent,false);
return new MyViewHolder(v);
}
public class MyViewHolder extends RecyclerView.ViewHolder
{
TextView updates_text ;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
updates_text = (TextView) itemView.findViewById(R.id.updates_text);
}
}
}
when I am using the code like:
recyclerview =
(RecyclerView) inflater.inflate(R.layout.fragment_admin_post, container, false);
getting the ClassCastException saying ConstraintLayout cannot be cast to recyclerview.
You need fix return in onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_admin_post, container, false);
recyclerView = view.findViewById(R.id.updates_recycler);
...
return view;
}
As the ClassCastException is printing the message, you cannot cast the ConstraintLayout to RecyclerView. its because earlier, when you had only recyclerview in your fragment_admin_post.xml file the root view in that file was a recycler view that could be type casted to a RecyclerView. now that you have wrapped it in a ConstraintLayout, you may inflate the view like this:
wrappinggConstraintLayout = (ConstraintLayout) inflater.inflate(R.layout.fragment_admin_post, container, false);
if you can show more detailed code sections, it would be more understandable.
I know that to show a list of views I can use recycler view with but what if I wanna reuse also my fragment logic too?
for example, if I have a fragment like this
XML
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.fragments.testview">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="hi"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment class
public class TestView extends Fragment {
private TextView txt;
#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.test, container, false);
initComponent(v);
return v;
}
private void hardTask1(){};
private void hardTask2(){};
//Some other hardtask
}
What I could do if I need to display a list of fragments in some activity but I don't want to rewrite all my TestView in the adapter?
In my Android app I have an Activity with RecyclerView and when the user clicks on an item I call another Activity that has a TabLayout with 2 fragments, each tab for a set of fields to be filled by the user.
When I do not use data binding, all is fine, but when I change the code to use data binding this error message appears:
FragmentManager: No view found for id 0x7f0c0072
(mypackage:id/container) for fragment
ContatosFormFragment2 [...]
FragmentManager: Activity state:
AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalArgumentException: No view found for id 0x7f0c0072 (mypackage:id/container) for fragment ContatosFormFragment2 [...] '.
The strange thing is that if I don’t include the ContatosFormFragment1 (so I have only one tab), the ContatosFormFragment2 works...
Also, if I change the tabs order, including ContatosFormFragment2 first an then ContatosFormFragment1, the error message is 'No view found [...] for fragment ContatosFormFragment1'
Note: I'll really aprecciate if you can focus on the main problem, I mean, don't worry about variable names, encapsulation, code style, etc ... This is an initial code that will be improved when working.
Below the code with and without data binding:
My Activity, no changes for data binding
public class ContatosFormActivity extends AppCompatActivity {
public User contato;
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
TextView tNome, tTipo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contatos_form);
Utils.initToolbar(this,false);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
Cursor cursor = (new DbController(getBaseContext())).carregaContatoById(getIntent().getIntExtra("contatoId", -1));
contato = new User(cursor.getString(cursor.getColumnIndexOrThrow(DbHelper.NOME)));
contato.setTipoPessoa(cursor.getString(cursor.getColumnIndexOrThrow(DbHelper.TIPO_PESSOA)));
}
private void setupViewPager(ViewPager viewPager) {
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new ContatosFormFragment1(), "Principal");
adapter.addFragment(new ContatosFormFragment2(), "Histórico");
viewPager.setAdapter(adapter);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
/* constructor + getItem + getCount + getPageTitle ...*/
}}
Code without data binding
public class ContatosFormFragment1 extends Fragment{
private EditText inputName;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contatos_tab1,container,false);
inputName = (EditText) view.findViewById(R.id.editText);
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
inputName.setText(contatosFormActivity.contato.getNome());
return view;
}
}
public class ContatosFormFragment2 extends Fragment{
private EditText inputName;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contatos_tab2,container,false);
inputTipoPessoa = (EditText) view.findViewById(R.id.tipo_pessoa);
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
inputTipoPessoa.setText(contatosFormActivity.contato.getTipoPessoa());
return view;
}
}
fragment_contatos_tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<android.support.design.widget.TextInputLayout
android:id="#+id/input_layout_name"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText"
android:layout_gravity="center_horizontal"
android:elegantTextHeight="false"
android:hint="Nome"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
fragment_contatos_tab2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<android.support.design.widget.TextInputLayout
android:id="#+id/input_layout_tipoPessoa"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tipo_pessoa"
android:layout_gravity="center_horizontal"
android:elegantTextHeight="false"
android:hint="Tipo de Pessoa"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
Code with data binding
public class ContatosFormFragment1 extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contatos_tab1,container,false);
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
FragmentContatosTab1Binding binding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_contatos_tab1);
binding.setContato(contatosFormActivity.contato);
return view;
}
}
public class ContatosFormFragment2 extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contatos_tab2,container,false);
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
FragmentContatosTab2Binding binding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_contatos_tab2);
binding.setContato(contatosFormActivity.contato);
return view;
}
}
fragment_contatos_tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="contato" type="net.simplifiedcoding.retrofitexample.models.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TextInputLayout
android:id="#+id/input_layout_name"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText"
android:layout_gravity="center_horizontal"
android:text="#{contato.nome}"
android:elegantTextHeight="false"
android:hint="Nome"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</layout>
fragment_contatos_tab2.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="contato" type="net.simplifiedcoding.retrofitexample.models.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TextInputLayout
android:id="#+id/input_layout_tipoPessoa"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tipo_pessoa"
android:layout_gravity="center_horizontal"
android:text="#{contato.tipoPessoa}"
android:elegantTextHeight="false"
android:hint="Tipo de Pessoa"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</layout>
I solved changing to this:
public class ContatosFormFragment1 extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
FragmentContatosTab1Binding binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_contatos_tab1, container, false);
View view = binding.getRoot();
binding.setContato(contatosFormActivity.contato);
return view;
}
}
public class ContatosFormFragment2 extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ContatosFormActivity contatosFormActivity = (ContatosFormActivity)getActivity();
FragmentContatosTab2Binding binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_contatos_tab2, container, false);
View view = binding.getRoot();
binding.setContato(contatosFormActivity.contato);
return view;
}
}
I am trying to do a simple test example with Android Data Binding. I only want to show in my fragment the text "test" in the EditText named "title", but this text is not shown. Here is my code:
TestVM.java
public class TestVM extends BaseObservable {
public TestVM() {}
#Bindable
public String getText() {
return "test";
}
}
fr_login.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="test"
type="de.theappguys.templateandroid.viewmodel.TestVM"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="20dp"
android:text="#{test.text}"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="#android:color/black"
/>
</RelativeLayout>
</layout>
FrLogin.java
#EFragment
public class FrLogin extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FrLoginBinding binding = DataBindingUtil.inflate(inflater, R.layout.fr_login, container, false);
return binding.getRoot();
}
...
build.gradle
android {
.....
dataBinding {
enabled = true
}
....
}
you need to set value to your binding
FrLoginBinding binding = DataBindingUtil.inflate(inflater, R.layout.fr_login, container, false);
binding.setTest(new TestVM());
Problem with your code is that there is no connection between your model and Fragment.
you have to bind your ViewModel as well. E.g
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FrLoginBinding binding = DataBindingUtil.inflate(inflater, R.layout.fr_login, container, false);
binding.setTest(new TestVM());
return binding.getRoot();
}
You should add this line in build.gradle (:app):
buildFeatures {
viewBinding true
}
private Context mContent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentBrandBinding binding = FragmentBrandBinding.inflate(inflater, container, false);
View view = binding.getRoot();
mContent = view.getContext();
return view;
}
I'm attempting to customize the fragment layout by returning my own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle). This inflates my custom view, but seems to stack the views instead of inflating within, I see everything at once. Any help is appreciated.
MyActivity.java:
public class MyActivity extends FragmentActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
ArrayListFragment list = new ArrayListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, list).commit();
}
}
public static class ArrayListFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
inflater.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, container);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String List[] = {"Larry", "Moe", "Curly"};
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, List));
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="THIS IS A BUTTON" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:layout_weight="1"
android:drawSelectorOnTop="false" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="No data" />
</LinearLayout>
I wasn't returning the new view within the onCreateView method of the ListFragment class. For instance:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main, null);
return view;
}
All works well now in the land of Android!
I think you'd better
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main, container, false);
return root;
}
optimized way and shot code
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list_alphabet, container, false);
}
getSupportFragmentManager().beginTransaction().add(android.R.id.content, list).commit();
List is not accepted, it's looking for a fragment.
use this pattern, works perfectly!
inflater.inflate(R.layout.list_layout, container, false);
public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
attachToRoot Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.