I am extending a Fragment called Scanlist. It is laid out properly and looks how I want it. Problem is I am unable to Override onInterceptTouchEvent on the extended Fragment. So I thought of extending ViewGroup, Override onInterceptTouchEvent and then add my Fragment to the ViewGroup. When I add my Fragment to the ViewGroup the Fragment is not showing up inside the ViewGroup. I know the ViewGroup is there because I am able to Log the onInterceptTouchEvent but the screen is blank.
Here is the Fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootview = (ViewGroup) inflater.inflate(R.layout.scanlist, container, false);
mRootview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mSharedData = new SharedData(mContext);
costomListViewArr = mSharedData.getvins();
Resources res = getResources();
mList = (ListView)mRootview.findViewById(R.id.list);
mAdapter = new Scanvinadapter(mActivity, costomListViewArr, res);
mList.setAdapter(mAdapter);
mAdapter.setimplements(this);
ViewGroup vg = new Scanlistview(mContext);
vg.addView(mRootview);
return vg;
}
Here is the ViewGroup
public class Scanlistview extends ViewGroup{
#SuppressWarnings("unused")
private final String TAG = this.getClass().getSimpleName();
LayoutInflater mInflater;
public Scanlistview(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
Log.v(TAG, "onInterceptTouchEvent");
return false;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
scanlist.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flScanlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/vinlist_bg">
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/vinlist_selector"
android:listSelector="#drawable/vinlist_selector"/>
</FrameLayout>
instead of FrameLayout add your custom FrameLayout with overriden
method, also you don't actually need that FrameLayout as it has only one child, so you can just place custom ListView in the layout file
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
First of all, I am absolute beginner for this, I'm sorry if this such a dumb mistakes. But I always got this error
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)' on a null object referenceat com.example.loginregister.ui.home.HomeFragment$1.onResponse(HomeFragment.java:104)
whenever I tried to run my app. I already changed getActivity() to HomeFragment.this , or getApplicationActivity() but still error, I'm stuck this for a long time because I not really understand how it's work, I hope someone can explain to me how to call context in fragment, here my java
public class HomeFragment extends Fragment {
private RecyclerView rvData;
private RecyclerView.Adapter adData;
private RecyclerView.LayoutManager lmData;
private List<DataModel> listData = new ArrayList<>();
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rvData = getActivity().findViewById(R.id.rv_user);
lmData = new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
rvData.setLayoutManager(lmData);
retrieveData();
return inflater.inflate(R.layout.fragment_home, container, false);
}
public void retrieveData(){
APIRequestData ardData = RetroServer.connectRetrofit().create(APIRequestData.class);
Call<ResponseModel> showData = ardData.ardRetrieveData();
showData.enqueue(new Callback<ResponseModel>() {
#Override
public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) {
int code = response.body().getCode();
String message = response.body().getMessage();
Toast.makeText(getActivity(), "Code: "+code+"| Message: "+message, Toast.LENGTH_SHORT).show();
listData = response.body().getData();
adData = new AdapterData(getActivity(),listData);
rvData.setLayoutManager(lmData);
adData.notifyDataSetChanged();
}
#Override
public void onFailure(Call<ResponseModel> call, Throwable t) {
Toast.makeText(getActivity(), "Fail to Retrieve Data", Toast.LENGTH_SHORT).show();
}
});
}
and here is my fragment_home.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_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_user"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/card_item"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
use this code
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
rvData = view.findViewById(R.id.rv_user);
return view;
}
As I see your layout is supposedly layout for a fragment. You should edit your code like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_home.xml, container, false);
rvData = inflate.findViewById(R.id.rv_user);
lmData = new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
rvData.setLayoutManager(lmData);
retrieveData();
return inflate;
}
If you really need your "context" basically the private fragment variable
private Context context;
Then you may retrieve it in onAttach method somewhat like this:
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
this.context = context;
}
This enables you to use context specific features like getting colors etc.
Hi I'm new to Android Studio, and I am trying to make a simple recycler view that contains a list of card view. The code runs just fine and every view is rendering fine when I run it, but then I decided to add background color to recycler view than everything just went wrong. The only thing I've changed is setting the background color of the recycler view. By the way, my recycler view lives in a fragment.
Here is what it looked like before I set the background color:
The xml file for the recycler view before change:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/recycler_view_item" />
</android.support.constraint.ConstraintLayout>
And here is what it looks like now, all I did is setting the background color of the recycler view:
Here is the new xml file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_dark"
tools:listitem="#layout/recycler_view_item" />
</android.support.constraint.ConstraintLayout>
My guess is that somehow the background color is covering my views?
By the way, I do notice an error occured in the logcat:
2018-12-21 22:02:05.515 20644-20644/com.steven97102gmail.todoassistant E/RecyclerView: No adapter attached; skipping layout
However, that error occurs even if I don't set the background, and it is working just fine.
Here is my class for frament:
public class RecycleFragment extends Fragment {
private RecyclerView recyclerView;
private RecyclerView.Adapter viewAdapter;
private RecyclerView.LayoutManager viewLayouManager;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.recyler_view, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// get and configure the recycle view
recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
// layout manager for recyler view
viewLayouManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(viewLayouManager);
// creates the initial cards
ArrayList<CardItem> card_lists = new ArrayList<>();
for (int i = 0;i<=10;i++){
CardItem card = new CardItem("TODO"+i,"12/" + i);
card_lists.add(card);
}
// adapter for recycler view, initialize the recycler view
viewAdapter = new RecyclerAdapter(card_lists);
recyclerView.setAdapter(viewAdapter);
// test add a new item
card_lists.add(0,new CardItem("Test Insert","12/16"));
viewAdapter.notifyItemInserted(0);
}
}
Here is my class for recycler view's adapter:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {
private ArrayList<CardItem> card_item_list;
// view holder is created from the recycler_card_item template
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView title_tv, date_tv;
public RecyclerViewHolder(LinearLayout layout) {
super(layout);
title_tv = layout.findViewById(R.id.card_item_title);
date_tv = layout.findViewById(R.id.card_item_date);
}
}
// take in a list of card items to initialize with
public RecyclerAdapter(ArrayList<CardItem> card_list) {
card_item_list = card_list;
}
#NonNull
#Override
// inflate and creates a viewholder objects, which is from the recycler care item template;
public RecyclerAdapter.RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
// create a new card item
LinearLayout cardLayout = (LinearLayout) LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recycler_card_item, viewGroup, false);
RecyclerViewHolder vh = new RecyclerViewHolder(cardLayout);
return vh;
}
#Override
// bind the CardItem class with the viewholder to complete the card
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
CardItem target_card = card_item_list.get(position);
holder.title_tv.setText(target_card.title);
holder.date_tv.setText(target_card.date);
}
#Override
public int getItemCount() {
return card_item_list.size();
}
}
In your code, you're trying to retrieve a recyclerview at Activity level:
recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
but the recyclerview is in your fragment. It is strange that you do not have any other errors, I would've expected the app to crash. Anyway, it should be solved in this way: change your onCreateView like this
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.recyler_view, container, false);
recyclerView = root.findViewById(R.id.recycler_view);
return root;
}
the previous line, the one that retrieved the recyclerview from the activity, is not needed anymore.
I'm new to android programming. I want to write an android program which contains two fragments. Designs' will be same but I can't write layout file twice as it has a lot of widgets so is there a way to handle this?
If I copy xml file widget ids' stay same and I can't reach them in my java class...
Lets assume you have fragment_container.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fraContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
What you need to do is to replace this container with one of the fragments in your program like this for example:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container);
if (findViewById(R.id.fraContainer) != null)
{
MyFragmentA myFragment = new MyFragmentA();
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fraContainer, myFragment)
.commit();
}
}
This will replace the fragment layout (container) with the fragment you want.
Now lets examine MyFragmentA, and MyFragmentB
public class MyFragmentA extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_both, container, false);
TextView x = (TextView)view.findViewById(R.id.textView);
x.setText("I am fragment A");
return view;
}
...
And the second fragment
public class MyFragmentB extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_both, container, false);
TextView x = (TextView)view.findViewById(R.id.textView);
x.setText("I am fragment B");
return view;
}
...
Both inflate the same fragment_both.xml, and both use the same TextView with the same ID, by referring to the view object!
I hope that helps you understand it.
You can simply use the same xml file in more fragments, like this:
Fragment A
public class FragmentA extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.your_layout, container, false);
...
return v;
}
}
Fragment B
public class FragmentB extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.your_layout, container, false);
...
return v;
}
}
i am new to android but i have problem using settext method . i have used settext method but when i load the project in emulator then the textview there is empty . it is blank screen i have no error while loading inside emulator
the code i have written is
package com.coded.fragments;
public class ChildFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
return rootView;
}
public void setText(String item) {
item = "<p>ABCDEFGHI</p><br><p>JKLMNOPQRSTUVWXYZ</p>";
TextView textview = (TextView) getView().findViewById(R.id.textView2);
textview.setText(Html.fromHtml(item));
}}
should i add any method to it and front end xml file i have written as this
activity_main.xml
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="216dp"
android:padding="10dp"
android:textAlignment="center"
android:textColor="#color/white" />
please friends check,let me know and thanks for your valuable time.
if i use this above code when i load it onto emulator it is giving blank screen there is no text displayed which i am passing from item from above code
Try this..
public class ChildFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
String item = "<p>ABCDEFGHI</p><br><p>JKLMNOPQRSTUVWXYZ</p>";
TextView textview = (TextView) rootView.findViewById(R.id.textView2);
textview.setText(Html.fromHtml(item));
return rootView;
}
Or
TextView textview;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
textview = (TextView) rootView.findViewById(R.id.textView2);
String item = "<p>ABCDEFGHI</p><br><p>JKLMNOPQRSTUVWXYZ</p>";
setText(item);
return rootView;
}
public void setText(String item) {
textview.setText(Html.fromHtml(item));
}
I am new to Android so my question may seem ridiculous but I cant figure it out.
I started creating an app some time ago and using 'Create new Android Activity' usually created a .java and .xml file for it, and everything worked. Now, after update when I use 'Create new Android Activity' it creates .java with class (which now extends ActionBarActivity and not Activity as before) and it adds a fragment_nameofactivity.xml + all things to make it work like internal class extending Fragment...
Now I used to do some ListView display on the page and without a fragment it all works great, but when fragment got introduced I can no longer findViewById(R.id.list_view) if its inside a fragment...
My question is do I need to place my whole functionality inside the class extending Fragment? I tried but it didn't work... Or do I still write all my functionality in the original class and then somehow access the listView in the fragment...
Here is the code:
public class PlayersActivity extends ActionBarActivity {
PlayerDataDatabaseAdapter playerDataHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_players);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
playerDataHelper = new PlayerDataDatabaseAdapter(this);
playerDataHelper.open();
displayPlayersList();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.players, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_players,
container, false);
return rootView;
}
}
private void displayPlayersList() {
Cursor cursor = playerDataHelper.getAllPlayers();
String [] columns = playerDataHelper.columnsToBind();
int [] to = new int[] {
R.id.player_name,
};
SimpleCursorAdapter dataAdapter = new SimpleCursorAdapter(this, R.layout.fragment_player_details, cursor, columns, to, 0);
ListView listView = (ListView) findViewById(R.id.players_list);
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
int player_id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
Intent intent = new Intent(PlayersActivity.this, EditPlayerActivity.class);
intent.putExtra("PlayerId", player_id);
startActivity(intent);
}
});
}
public void addNewPlayer(View view) {
Intent intent = new Intent(this, AddPlayerActivity.class);
startActivity(intent);
}
}
Fragment_players.xml
<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="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="uk.co.eximage.soccermum.PlayersActivity$PlaceholderFragment" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:text="#string/players"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal = "true"
android:layout_below="#+id/textView1"
android:onClick="addNewPlayer"
android:text="#string/add_player" />
<ListView
android:id="#+id/players_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/button1"
>
</ListView>
</RelativeLayout>
activity_players.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="uk.co.eximage.soccermum.PlayersActivity"
tools:ignore="MergeRootFrame" />
Running this returns NullPointerException on the line that tries to get players_list:
ListView listView = (ListView) findViewById(R.id.players_list);
after this listView is null.
What am I doing wrong?
And finally do I need fragments? Maybe I should just remove them and do it the 'old' way with one view per page?
You need to iniaitlize ListView in Fragment
ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_players,
container, false);
listView = (ListView)rootView. findViewById(R.id.players_list);
playerDataHelper = new PlayerDataDatabaseAdapter(getActivity());
playerDataHelper.open();
displayPlayersList();
The ListView belongs to fragment_players.xml. Move all your code related to fragment in onCreateView.
Edit:
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_players,
container, false);
listView = (ListView)rootView. findViewById(R.id.players_list);
playerDataHelper = new PlayerDataDatabaseAdapter(getActivity());
playerDataHelper.open();
displayPlayersList();
return rootView;
}
private void displayPlayersList() {
Cursor cursor = playerDataHelper.getAllPlayers();
String [] columns = playerDataHelper.columnsToBind();
int [] to = new int[] {
R.id.player_name,
};
SimpleCursorAdapter dataAdapter = new SimpleCursorAdapter(getActivity(), R.layout.fragment_player_details, cursor, columns, to, 0);
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
int player_id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
Intent intent = new Intent(getActivity(), EditPlayerActivity.class);
intent.putExtra("PlayerId", player_id);
startActivity(intent);
}
});
}
}
Fragments were introduced to better support the tablet form factor. If you don't plan to rearrange your display (ie. show list and detail view together), you don't need fragments and can go the old way.
You should have to initialize Listview from fragment rootView
Either you have to Declare ListView globally and intialize inside onCreateView of Fragment or have to declare View rootView globally and initialize listview by
ListView listView = (ListView) rootView .findViewById(R.id.players_list);