Trying to load a page that only contains a listview listing some keys of a firebase realtime database. Currently, once the page loads, the emulated mobile app crashes and I have no idea why.
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:id="#+id/terms"
/>
</RelativeLayout>
Java:
DatabaseReference termsReference = database.getReference("users/"+userID+"/terms");
ArrayList<String> terms = new ArrayList<String>();
termsReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
terms.add(singleSnapshot.getKey().toString());
}
ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, terms);
listViewTerms.setAdapter(arrayAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The terms arraylist only contains one string, so terms = ["term1"]
What I've found is that the app doesn't crash when I comment out the following lines:
ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, terms);
listViewTerms.setAdapter(arrayAdapter);
but I need those lines, so I'm kind of stumped. Any help would be greatly appreciated, thank you.
Forgot to properly initalize listViewTerms. Added listViewTerms = (ListView)findViewById(R.id.terms); into the Java method.
Related
I am getting an error when trying to set my view to display the ListView for the file I want to display(text file). I am pretty sure it has something to do with the XML. I just want to display the information from this.file = fileop.ReadFileAsList("Installed_packages.txt");. My code:
public class Main extends Activity {
private TextView tv;
private FileOperations fileop;
private String[] file;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.fileop = new FileOperations();
this.file = fileop.ReadFileAsList("Installed_packages.txt");
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.TextView01);
ListView lv = new ListView(this);
lv.setTextFilterEnabled(true);
lv.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, this.file));
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
setContentView(lv);
}
}
list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp"
android:textSize="16sp"
android:textColor="#000">
</LinearLayout>
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="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1">
<ScrollView
android:id="#+id/SCROLLER_ID"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5sp"
android:id="#+id/TextView01"
android:text="#string/hello"/>
</ScrollView>
</LinearLayout>
The ArrayAdapter requires the resource ID to be a TextView XML exception means you don't supply what the ArrayAdapter expects. When you use this constructor:
new ArrayAdapter<String>(this, R.layout.a_layout_file, this.file)
R.Layout.a_layout_file must be the id of a xml layout file containing only a TextView(the TextView can't be wrapped by another layout, like a LinearLayout, RelativeLayout etc!), something like this:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
// other attributes of the TextView
/>
If you want your list row layout to be something a little different then a simple TextView widget use this constructor:
new ArrayAdapter<String>(this, R.layout.a_layout_file,
R.id.the_id_of_a_textview_from_the_layout, this.file)
where you supply the id of a layout that can contain various views, but also must contain a TextView with and id(the third parameter) that you pass to your ArrayAdapter so it can know where to put the Strings in the row layout.
Soution is here
listitem.xml
<?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" >
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</TextView>
</LinearLayout>
Java code :
String[] countryArray = {"India", "Pakistan", "USA", "UK"};
ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.listitem,R.id.textview, countryArray);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
If you are getting that message when you are extending an ArrayAdapter, you are getting that error because you have not provided the correct resource id to display the item. Call the super class in the constructor and pass in the resource id of the TextView:
//Pass in the resource id: R.id.text_view
SpinnerAdapter spinnerAddToListAdapter = new SpinnerAdapter(MyActivity.this,
R.id.text_view,
new ArrayList<>());
Adapter:
public class SpinnerAdapter extends ArrayAdapter<MyEntity> {
private Context context;
private List<MyEntity> values;
public SpinnerAdapter(Context context, int textViewResourceId,
List<MyEntity> values) {
//Pass in the resource id: R.id.text_view
super(context, textViewResourceId, values);
this.context = context;
this.values = values;
}
The problem is in the line:
lv.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, this.file));
Because when i change it to:
lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, this.file));
It works!
I'm currently developing the android application using the Android Studio, Firebase RealTime Database.
I'd like to make the List show up on the screen, but the List didn't show up.
I believe the application failed to read the data from the firebase.
(I made the debug and the value of the result.size() on the
ResultsAdmin.java Log.e("The read success: " ,"su"+result.size()); was 0. So, I think data transmission was conducted successfully, but the contents are empty.)
I really appreciate helpful suggestions as to what caused this situation.
Followings are the related codes.
activity_tests.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Tests">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_tests" />
</RelativeLayout>
content_tests.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/test_listview">
</ListView>
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center|bottom"
android:layout_marginBottom="20dp"
android:visibility="gone" />
</FrameLayout>
test_item.xml
<?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="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginBottom="#dimen/activity_horizontal_margin">
<TextView
android:id="#+id/item_textView"
android:layout_width="wrap_content"
android:layout_height="?android:actionBarSize"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/item_imageView"
android:gravity="center_vertical|center_horizontal"/>
<ImageView
android:id="#+id/item_imageView"
android:layout_width="?android:actionBarSize"
android:layout_height="?android:actionBarSize" />
<Button
android:layout_margin="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:id="#+id/item_button"
android:background="#color/colorPrimaryDark"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
ResultsAdmin.java(I abbreviate the import and package statements.)
public class ResultsAdmin extends AppCompatActivity {
private FirebaseDatabase database;
private FirebaseAuth auth;
private DatabaseReference myRef;
private ProgressBar progressBar;
private ListView listView;
private ResultsAdmin.TestAdapter testAdapter;
ArrayList<String> result=new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
auth=FirebaseAuth.getInstance();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tests);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
database=FirebaseDatabase.getInstance();
myRef=database.getReference();
listView=findViewById(R.id.test_listview);
testAdapter=new ResultsAdmin.TestAdapter(ResultsAdmin.this,result);
listView.setAdapter(testAdapter);
getResults();
}
public void getResults(){
myRef.child("Results").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
result.clear();
for(DataSnapshot snapshot:dataSnapshot.getChildren()){
result.add(snapshot.getKey()); //keyを取得している。Verbal~のこと。
}
testAdapter.dataList=result;
testAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
Log.e("The read success: " ,"su"+result.size());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
progressBar.setVisibility(View.GONE);
Log.e("The read failed: " ,databaseError.getMessage());
}
});
}
class TestAdapter extends ArrayAdapter<String> {
private Context mContext;
ArrayList<String> dataList;
public TestAdapter( Context context,ArrayList<String> list) {
super(context, 0 , list);
mContext = context;
dataList = list;
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.test_item,parent,false);
((ImageView)listItem.findViewById(R.id.item_imageView)).setImageDrawable
(ContextCompat.getDrawable(mContext,R.drawable.ic_assessment_black_24dp));
((TextView)listItem.findViewById(R.id.item_textView)).setText(dataList.get(position));
((Button)listItem.findViewById(R.id.item_button)).setText("View");
((Button)listItem.findViewById(R.id.item_button)).setOnClickListener(new
View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(ResultsAdmin.this,ResultsAdminDetailed.class);
intent.putExtra("test",dataList.get(position));
startActivity(intent);
}
});
return listItem;
}
}
}
You should add a listener to your list view or better use Recyclerview and 'OnScrolled listener' on it and make maintain a boolean to show progress bar and when data is loaded disable the progress bar. Recommened- Use pagination.
I have the result of a sql query expressed in this way :
//The column attributes of a result table
ArrayList<String> columns_attributes;
// This contains the data of every row of the result
ArrayList<ArrayList<String>> rows_data;
How can i dinamically display it on an activity ? Thanks
MainActivity
public class MainActivity extends AppCompatActivity {
List<String> list = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list.add("Android");
list.add("iPhone");
list.add("Windows");
list.add("Blackberry");
list.add("Mac");
list.add("Laptop");
list.add("LCD");
list.add("Dell");
ArrayAdapter adapter = new ArrayAdapter<String>(MainActivity.this, R.layout.list_view_item, list);
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "Clicked: " + list.get(position), Toast.LENGTH_SHORT).show();
}
});
listView.setAdapter(adapter);
}
}
activity_main.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.vzw.www.listviewalert.MainActivity">
<ListView
android:id="#+id/mobile_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
list_view_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:textSize="16dip"
android:textStyle="bold" >
</TextView>
You can iterate over these list with simple for loops like this:
// for columns
for (String colAttr : columns_attributes) {
// do something with the string value
}
// for rows
for (List<String> row : rows_data) {
for (String rowAttr : row) {
// do something with the string value
}
}
To display a dynamic amount of data, a ListView is recommended to do the job. If you just want to display those strings, you can use a ListActivity and assign a ArrayAdapter to that ListView with the setListAdapter() method.
You may want to check this tutorial to get this done.
http://androidexample.com/Create_Listview_With_ListActivity_-_Android_Example/index.php?view=article_discription&aid=66
How do I create a working ListView in Android?
I am not looking for you to just fix my code, but am looking for a simple working example of a ListView in Android so I can understand the process of creating one and working with it. But I have included my code so you can see where I am coming from and what I have been trying.
I have done the following and had no success:
--
Made a xml layout with only a TextView item in it:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/dir_text_view"
/>
Created the following class as per the instructions at the following tutorial:
http://www.vogella.com/tutorials/AndroidListView/article.html
public class DataTempleArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public DataTempleArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
}
And in the main activity I have a snippet of code where I attempt to add a list of strings to the ArrayList associated with the DataTempleArrayAdapter here:
int i;
for (i=0;i<dirContents.length;i++) {
dirList.add(dirContents[i]);
//Toast.makeText(this, dirList.get(i), Toast.LENGTH_SHORT).show();
}
adapter.notifyDataSetChanged();
dirList is successfully populated, while the adapter doesn't update the ListView at all.
--
Before you ask for it, here I am including the rest of the relevant code:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
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="org.hacktivity.datatemple.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:hint="#string/directory"
android:ems="10"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/dirEditText" />
<Button
android:text="→"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/dirButton"
android:onClick="populateDirList" />
</LinearLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:id="#+id/dirListView" />
</LinearLayout>
</RelativeLayout>
And alas the MainActivity class:
public class MainActivity extends AppCompatActivity {
ListView dirListView;
EditText et;
DataTempleArrayAdapter adapter;
ArrayList<String> dirList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dirListView = (ListView) findViewById(R.id.dirListView);
et = (EditText) findViewById(R.id.dirEditText);
dirList = new ArrayList<String>();
dirListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(),
"Click ListItem Number " + position, Toast.LENGTH_LONG)
.show();
populateDirList(view);
}
});
ArrayList<String> dirList = new ArrayList<String>();
adapter = new DataTempleArrayAdapter(this,
R.id.dir_text_view, dirList);
dirListView.setAdapter(adapter);
}
public void populateDirList (View view) {
File f;
// NO INPUT.
if (et.getText().toString().equals("")) {
Toast.makeText(this, "empty string", Toast.LENGTH_SHORT).show();
return;
}
f = new File(et.getText().toString());
if (f == null) { return; }
String dirContents[] = f.list();
if (dirContents == null) { return; }
dirList = new ArrayList<String>(Arrays.asList(f.list()));
adapter.clear();
int i;
for (i=0;i<dirContents.length;i++) {
dirList.add(dirContents[i]);
//Toast.makeText(this, dirList.get(i), Toast.LENGTH_SHORT).show();
}
adapter.notifyDataSetChanged();
}
}
One of the best resources for understanding ListView is indeed the
one you mentioned from Vogella
Another cool resource to understand how the the
notifyDataSetChanged() method works in ListView this post from StackOverflow
For a short, simple explanation of how to use CustomLayouts in
ListView (without the ViewHolder pattern) check another of the best
references available: Mkyong
Discussing the benefits of the ViewHolder pattern in ListView:
check this StackOverflow post
Concise example and explanation of the ViewHolder pattern in
ListView: check this example from JavaCodeGeeks
And to fix your code I think the answer given before is only part of the problem:
You must indeed comment the line
//ArrayList<String> dirList = new ArrayList<String>();
because, like #F43nd1r mentioned this would also be a different instance of a list passed into the adapter
but there is more, when you do this:
dirList = new ArrayList<String>(Arrays.asList(f.list()));
you are instantiating a new, different, list, the old reference held by the adapter will NOT be changed... it will still hold the OLD object list
you should perhaps substitute it for something like:
dirList.clear();
dirList.addAll(Arrays.asList(f.list()));
Hope this helps!
Excerpt from your code:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
dirList = new ArrayList<String>();
//...
ArrayList<String> dirList = new ArrayList<String>();
adapter = new DataTempleArrayAdapter(this,
R.id.dir_text_view, dirList);
//...
}
I bet you already see what the problem is, but in case you don't: You have a field and a local variable with the same name. You pass the local variable to the adapter. It is only naturally that the adapter does not react to changes on the field, as it has no knowledge of its existence.
I think what you have done wrong is to supply a UI Component to the Array Adapter with:
adapter = new DataTempleArrayAdapter(this, R.id.dir_text_view, dirList);
The second item should not be an ID, but a layout file. Android have already implemented a List item layout with a textview that you can use: android.R.layout.simple_list_item_1.
so replace your row with
adapter = new DataTempleArrayAdapter(this, android.R.layout.simple_list_item_1, dirList);
and you are one step closer.
(This way you don't need your "xml layout with only a TextView item in it")
I'm trying to make an audio recorder for which I want to display a list of recordings done till now.
I'm able to get the list recorded files from my SD card in to an ArrayList, but my app crashes when it tries to populate the list view.
ListRecordings.java is called using an Intent from MainActivity.java.
Here is the for ListRecordings.java:
public class ListRecordings extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.listrecordings);
ListView lv;
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/MyAudioRecorder";
ArrayList<String> FilesInFolder = GetFiles(path);
lv = (ListView) findViewById(R.id.filelist);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.textlayout,
FilesInFolder);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
// Clicking on items
}
});
}
public ArrayList<String> GetFiles(String DirectoryPath) {
ArrayList<String> MyFiles = new ArrayList<String>();
File f = new File(DirectoryPath);
f.mkdirs();
File[] files = f.listFiles();
if (files.length == 0)
return null;
else {
for (int i = 0; i < files.length; i++)
MyFiles.add(files[i].getName());
}
return MyFiles;
}
}
Here's the code for listrecordings.xml
<?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" >
<ListView
android:id="#+id/filelist"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Here's the code for textlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp"
android:textStyle="bold" >
</TextView>
Any help is appreciated.
I've just started with android so excuse me if i made any lame mistakes.
Thanks
You missing this line in onCreate()
super.onCreate(savedInstanceState);
Add something like this
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.textlayout,
R.id.textview_id_in_textlayout,FilesInFolder);
I hope this will help.