I am trying to create a simple Icon+Text ListView but it does not work.
I am using 2.1 Android SDK.
My main class is very small slightly modified from the tutorial:
public class Stuffs extends ListActivity {
static final String[] COUNTRIES = new String[] {"A", "B","C"};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, R.id.title, COUNTRIES));
}
}
and my list_item.xml file is this:
<?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="wrap_content"
android:orientation = "horizontal">
<ImageView
android:id = "#+id/icon"
android:src="#drawable/icon" />
<TextView
android:id = "#+id/title"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
</LinearLayout>
I have also created a "drawable" directory in my res directory and copied a "icon.png" into it.
But any time I try to run this the application hangs up unexpected in my android emulator.
Am I missing something?
I found an excellent example of how to create lists with icons here:
http://commonsware.com/Android/excerpt.pdf
The The Busy Coder's Guide to Android Development book in general is very enlightening.
Related
I found another question about this same problem but the code had an error in a place that doesn't seem to apply to mine. Sorry if this is a repeat.
I have an activity that should display a list of subjects that have been entered by the user. My problem is that when I run the app, only the first item in the ArrayList is being displayed. I honestly have no clue where the error is, so all my relevant code is below, including the XML. I'd appreciate any help anyone could give me.
EDIT: yes I have debugged. Both the cursor and ArrayList contain the expected items, but the ListView is only displaying the first one.
The relevant function in my DatabaseHelper class:
public Cursor getSubjects(int level){
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("select * from "+TABLE_NAME + " where " + COL_3 + "="+level,null);
return res;
}
The code from my activity class:
public class Level1Activity extends Activity implements OnClickListener {
private Button subject1Btn, level2Btn, level3Btn;
DatabaseHelper myDb;
private ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level1);
myDb = new DatabaseHelper(this);
//set up buttons
subject1Btn = (Button)findViewById(R.id.subject1);
level2Btn = (Button)findViewById(R.id.Level2);
level3Btn = (Button)findViewById(R.id.Level3);
level2Btn.setOnClickListener(this);
level3Btn.setOnClickListener(this);
lv = (ListView)findViewById(R.id.subjectList);
Cursor subjectCursor = myDb.getSubjects(1);
ArrayList<String> mArrayList = new ArrayList<String>();
for(subjectCursor.moveToFirst(); !subjectCursor.isAfterLast(); subjectCursor.moveToNext()) {
mArrayList.add(subjectCursor.getString(1));
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this, R.layout.subject_list_item, mArrayList);
lv.setAdapter(arrayAdapter);
}
And the relevant code from my xml files:
subject_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- Single List Item Design -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="120dp"
android:padding="10dip"
android:textSize="16dip"
android:textColor="#ffffffff"
android:textStyle="bold" >
</TextView>
activity_level1.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/app_back">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="8">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="2dp">
<Button
android:id="#+id/subject1"
android:layout_width="match_parent"
android:layout_height="120dp"
android:onClick="onClick"
android:text="Subject 1"
android:textColor="#ff000000"
android:textSize="20sp"
android:textStyle="bold"
android:background="#ffff0000"
android:layout_margin="4dp"/>
<ListView
android:id="#+id/subjectList"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<Button
android:id="#+id/newSubject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|right"
android:background="#ff444444"
android:onClick="onClick"
android:text="+"
android:textColor="#ffff0000"
android:textSize="80sp" />
</LinearLayout>
</ScrollView>
Regarding only 1 item is displaying, did you debug how many items are there in Cursor? Or how many items are getting added in mArrayList? Try debugging it once.
Suggestion:
You should write cursor iteration code in helper class itself, this is to avoid database operations code in Activity class.
Include below code in getSubjects() method and return ArrayList type:
Cursor subjectCursor = myDb.getSubjects(1);
ArrayList<String> mArrayList = new ArrayList<String>();
for(subjectCursor.moveToFirst(); !subjectCursor.isAfterLast(); subjectCursor.moveToNext()) {
mArrayList.add(subjectCursor.getString(1));
}
I figured out an answer to my problem. Thanks everyone for the help and suggestions with debugging.
If anyone else is having this same problem here is the solution:
ListView itself is scrollable. It will not work inside of a ScrollView, hence in my case it was only displaying one a single item from an ArrayList of several. By taking it out of the ScrollView you can assign the height you want it to take up on your screen and it will scroll through the items automatically.
I am trying to create a simple Listview in android, with arabic text in each item. The problem is, the displayed text is totally corrupted and not arabic. I have set my Android Studio encoding to UTF-8 but that did not help.
Below is my android code
public class CategoryActivity extends AppCompatActivity {
// Array of strings...
String[] mobileArray = {"الرياضي","عربي وعالمي","الثقافي","دنيا","الامارات"};
//String[] mobileArray ={"zaid", "ahmad", "abdallah"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category);
ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.activity_listview, mobileArray);
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
}
}
Below are my xml files,
activity_category.xml
<?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"
android:orientation="vertical">
<ListView
android:id="#+id/mobile_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
activity_listview.xml
<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"
android:gravity="right">
</TextView>
Note: Hardcoding the string array in the xml file works, but I don't want that. I want to fetch the array from database at runtime.
You put array in values.xml with <string-array>.
put your arabic array inside string.xml in the values-ar folder inside the res.
You can allow RTL from your AndroidMenifest.xml by using "android:supportsRtl="true" with <application> tag.
I am new to Android development and I have been looking through Q's/Documentation but unable to find direction on what my end game is.
I am building what could be described as a 'content aggregator' and at current I am struggling to see how I can set an activity that proceeds a click on each position to instigate either an Instagram profile mWebView or an API call. Currently my InstagramList.java is as follows -
public class InstagramList extends Activity {
ListView list;
String[] web = {
"Kyary Pamyu Pamyu",
"Tokyo Girls' Style",
"Haruka Nakagawa",
"Nemu Yumemi",
"Moga Mogami",
"Ayane Fujisaki",
"Koda Kumi",
"Atsuko Maeda",
"Tomomi Itano",
"Haruna Kojima",
"Utada Hikaru",
"Shibasaki Ko",
"Taeyon",
"Tiffany",
"Jessica",
"Sooyoung",
"Sunny",
"Laboum",
"YeEun",
"Yubin",
"Hyelim"
};
Integer[] imageId = {
R.drawable.kyary,
R.drawable.tgs,
R.drawable.haruka,
R.drawable.nemu,
R.drawable.moga,
R.drawable.ayane,
R.drawable.koda,
R.drawable.atsuko,
R.drawable.tomomi,
R.drawable.haruna,
R.drawable.utada,
R.drawable.shibasaki,
R.drawable.taeyon,
R.drawable.tiffany,
R.drawable.jessica,
R.drawable.sooyoung,
R.drawable.sunny,
R.drawable.laboum,
R.drawable.yeeun,
R.drawable.yubin,
R.drawable.hyelim
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.instagram_main);
CustomList adapter = new
CustomList(InstagramList.this, web, imageId);
}
}
The xml for this is as follows -
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</TableRow>
</TableLayout>
Any pointers on how best to either modify this to allow better control of these variables or on a possible solution would be greatly received. Apologies if this has been asked in a similar vein before.
I observed that you are using two arrays. In place of this you can create a class with one member as string (web) and other as int (imageId). In addition to this you can add one variable for possible action as you mention there can be different actions. In adapter you can add tag on view and click listener so you can perform different actions on different item click.
Hope I understand your problem correctly. Let me know if you need more detail.
Check out this. In onItemClick method in MainActivity do what you want.
EDIT 2:
In my MainActivity I have a function (displayData) that displays the substitutions for my school.
public void displayData(List<Schoolday> results) {
TabLayout mainTabLayout = (TabLayout) findViewById(R.id.mainTabLayout);
ViewPager mainViewPager = (ViewPager) findViewById(R.id.mainViewPager);
// draw the tabs depending on the days from the file
mainTabLayout.removeAllTabs();
for (int n = 0; n < results.size(); n++) {
List<Subject> subjectsToDisplay = new ArrayList<>();
if (myPreferences.getBoolean(SHOW_WHOLE_PLAN, true)) {
subjectsToDisplay = results.get(n).getSubjects();
} else {
List<Subject> tempSubjectsToDisplay;
tempSubjectsToDisplay = results.get(n).getSubjects();
for (int i = 0; i < tempSubjectsToDisplay.size(); i++) {
if (tempSubjectsToDisplay.get(i).getCourse().contains(myPreferences.getString(CLASS_TO_SHOW, "None"))) {
subjectsToDisplay.add(tempSubjectsToDisplay.get(i));
}
}
}
results.get(n).setSubjects(subjectsToDisplay);
// only create a tab if there's any information to show within that tab
if (results.get(n).getSubjects().size() > 0) {
mainTabLayout.addTab(mainTabLayout.newTab().setText(results.get(n).getDate().substring(0, 6)));
}
}
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), mainTabLayout.getTabCount(), results);
mainViewPager.setAdapter(pagerAdapter);
mainViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mainTabLayout));
mainTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
mainViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
This is my main layout:
<?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:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="#+id/mainTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabGravity="fill" />
<android.support.v4.view.ViewPager
android:id="#+id/mainViewPager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/mainTabLayout" />
</RelativeLayout>
And this is the layout of the fragment that represents a page in the ViewPager:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/mainSwipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/mainRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
Whenever a refresh is triggered by the SwipeRefreshLayout I need the function displayData to be called.
How can I call this function since the call comes from within a fragment/page from the ViewPager and displayData is not static?
Old question:
I've been searching around quite a while but couldn't find an answer. Maybe I've searched for the wrong thing - just pointing me to that would already help.
My project (Vertretungsplan on github) displays the substitution plan for my school which is available to view/download as an xml file (xml file from school website). I then display the data in my app.
I have a TabLayout (different tabs represent different days) and a connected ViewPager. Each page is using a fragment. Each fragment includes a RecyclerView (to display the results) which is wrapped in a SwipeRefreshLayout.
When I want to refresh the data with the SwipeRefreshLayout I need to download all the data again and then update all the pages as well as the TabLayout(a new day might have a been added so a new tab will be needed). Since my refresh happens inside a fragment but I'm referencing the TabLayout as well as the ViewPager from my MainActivity I have no clue how to properly access all the elements in order to update the content.
My idea was to set up a Broadcast to let my MainActivity know that it needs to refresh the page since it originally set up the whole layout but maybe there is a better solution for that?
I'm kinda new to stackoverflow so feel free to correct me in the way of asking things here! If there's anything other information you need just ask me!
I appreciate your help!!
There are a couple ways to implement what you are asking. The most direct way is to create an interface for the Activity that the Fragment uses. See the docs here:
http://developer.android.com/training/basics/fragments/communicating.html
The other option, which decouples the Fragment from the Activity (which some may see as an advantage) is to use an Intent. With that approach, you need to look into the onNewIntent method, as it is not obvious exactly how it works.
Either one should be fine, especially since you are exploring ideas at this point.
This question already has answers here:
ArrayAdapter requires ID to be a TextView error
(4 answers)
Closed 8 years ago.
I tried this tutorial http://windrealm.org/tutorials/android/android-listview.php "A Simple Android ListView Example"
But in my test in Eclipse I've crash in android application.
In LogCat I've this:
04-11 20:17:24.170: E/AndroidRuntime(7062):
java.lang.IllegalStateException: ArrayAdapter requires the resource ID
to be a TextView
Why the crash ?
class java
private ListView mainListView;
private ArrayAdapter<String> listAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mains);
mainListView = (ListView) findViewById(R.id.mainListView);
String[] xRemote = Remote.split(";");
ArrayList<String> planetList = new ArrayList<String>();
planetList.addAll(Arrays.asList(xRemote));
listAdapter = new ArrayAdapter<String>(this, R.layout.simplerow,
planetList);
listAdapter.addAll(xRemote);
mainListView.setAdapter(listAdapter);
mains.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">
<ListView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/mainListView">
</ListView
</LinearLayout>
simplerow.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/rowTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
</LinearLayout>
Use
listAdapter = new ArrayAdapter<String>(this, R.layout.simplerow,
R.id.rowTextView, planetList);
The documentation says:
By default this class expects that the provided resource id references
a single TextView. If you want to use a more complex layout, use the
constructors that also takes a field id. That field id should
reference a TextView in the larger layout resource.
In simplerow.xml remove the LinearLayout and directly use TextView as the root