My custom CursorAdapter does not display the items - android

I am using a custom CursorAdapter and have values in DB but the problem is that the values are not displaying in the custom ListView. I searched in SO but could not find my answer.
By debugging I found out that the 2 methods in cursor adapter bindView() and the newView() are not executing but the constructor is executing.I am not sure what is happening overall. So my question is why are the ListView items not getting displayed ?
Here is my code and I am only posting relevant code so if there is any additional code needed please comment so that I will edit accordingly.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//a listview object
notesView = (ListView)findViewById(R.id.listView);
//an object of SQLiteOpenHelper class
dbhelper = new DataBaseHelper(this);
//cursor object
passCursor = dbhelper.fetchAllNotes();
// the custom cursor adapter class object
dataCursor = new CustomCursor(this,passCursor);
notesView.setAdapter(dataCursor);
notesView.setOnItemClickListener(this);
bar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(bar);
}
Here is the CursorAdapter source code:
public class CustomCursor extends CursorAdapter {
private static final String NOTE_TITLE = "title";
private static final String RECORD_ID = "_id";
private static final String RECORD_DATE = "date";
private static final String DELETE_FLAG="deleteflag";
LayoutInflater inflater;
TextView tv, recordID, dateET;
LinearLayout ll;
String getText, existsRecordID;
long datevalue;
SimpleDateFormat dateFormatter;
String listViewHeight;
Context cont;
int getDeleteFlag;
String listHeightValue;
LinearLayout.LayoutParams params;
Cursor getCursor;
CustomCursor(Context context, Cursor c) {
super(context, c, 0);
cont= context;
getCursor= c;
//inflater = LayoutInflater.from(context);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dateFormatter = new SimpleDateFormat("dd-MM-yyyy HH:mm");
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(R.layout.customlistview, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
getDeleteFlag = cursor.getInt(cursor.getColumnIndex(DELETE_FLAG));
ll = (LinearLayout)view.findViewById(R.id.listViewLayout);
setListViewHeight(ll,context);
getText = cursor.getString(cursor.getColumnIndex(NOTE_TITLE));
existsRecordID = cursor.getString(cursor.getColumnIndex(RECORD_ID));
datevalue = cursor.getLong(cursor.getColumnIndex(RECORD_DATE));
Date newdate = new Date(datevalue);
recordID = (TextView) view.findViewById(R.id.recordID);
tv = (TextView) view.findViewById(R.id.content);
dateET = (TextView) view.findViewById(R.id.date);
tv.setText(getText.trim());
recordID.setText(existsRecordID);
dateET.setText(dateFormatter.format(newdate));
}
}
EDIT 1
Here is the main layout,
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragplacement"
xmlns:android="http://schemas.android.com/apk/res/android">
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:gravity="top|left"
android:descendantFocusability="blocksDescendants"
tools:context="com.random.simplenotes.MainActivity">
<android.support.v7.widget.Toolbar
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="wrap_content"
android:id="#+id/toolbar"
>
</android.support.v7.widget.Toolbar>
<ListView
android:layout_width="match_parent"
android:clickable="true"
android:layout_height="match_parent"
android:id="#+id/listView"
android:scrollbars="vertical"
/>
</LinearLayout>
</FrameLayout>
Here is the layout for the listView item,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:background="#color/PeachPuff"
android:id="#+id/listViewLayout"
android:layout_margin="7dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Here is the content.."
android:gravity="center"
android:id="#+id/content"
android:textColor="#color/black"
android:focusable="false"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="12/09/15"
android:layout_margin="10dp"
android:focusable="false"
android:id="#+id/date" />
<TextView
android:layout_width="1dp"
android:layout_height="1dp"
android:visibility="gone"
android:focusable="false"
android:id="#+id/recordID" />
</LinearLayout>
Code for the method setListViewHeight()
private void setListViewHeight(LinearLayout ll, Context con) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(con);
listHeightValue = sp.getString(con.getResources().getString(R.string.listViewHeightkey),Constants.DEFAULT_VALUE_LISTVIEW_HEIGHT);
switch (listHeightValue)
{
case "Tiny":
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,200);
ll.setLayoutParams(params);
break;
case "Medium":
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,220);
ll.setLayoutParams(params);
break;
case "Large":
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,250);
ll.setLayoutParams(params);
break;
default:
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,150);
ll.setLayoutParams(params);
}
}

The problem is your haven't set the orientation of the LinearLayout in your main layout, so it defaults to horizontal.
This means the ListView is placed next to the Toolbar, but the width of the Toolbar is set to match_parent, so there is no room left for the ListView.
Add the following attribute to the LinearLayout in activity_main.xml, so the ListView will be placed below the Toolbar:
android:orientation="vertical"
Also, the following call might need to be removed from bindView():
setListViewHeight(ll,context);
The height of the ListView is already set properly in XML, this call might mess it up (i can only assume, since you haven't posted the implementation of setListViewHeight()).

Check if your Cursor is empty... if you are sure that it is not empty then for patching call the following code in the last line in out Activity -> onCreate() ...
dataCursor.notifyDataSetChanged();

Related

Show single item at a time in ListView

I am working on a WearOS app. I am using a ListView to show a list of strings. Right now, the ListView looks like this:
I want a single row to take up the entire screen. Once a user swipes up, then Row 2 takes up the entire screen. Swipe up again and Row 3 takes up the entire screen, etc. So like this:
I came across this link, which is exactly what I want to do, but the first method doesn't work and the second method suggests a library, but I don't want to use a library for what seems like a pretty simple task. I don't want to use RecyclerView. Thank you for your help.
Here is my XML file for the main activity, which is where the ListView is.
<?xml version="1.0" encoding="utf-8"?>
<android.support.wear.widget.BoxInsetLayout 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"
android:background="#color/dark_grey"
android:padding="#dimen/box_inset_layout_padding"
tools:context=".MainActivity"
tools:deviceIds="wear">
<!-- Change FrameLayout to a RelativeLayour -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/inner_frame_layout_padding"
app:boxedEdges="all">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
</android.support.wear.widget.BoxInsetLayout>
Try the following (The idea here is to programmatically set the height of the textView to the height of the screen):
1) MnnnnnnnActivity.class:----------
public class MnnnnnnnActivity extends AppCompatActivity {
private ListView lv;
private CustomAdapter customAdapter;
private String[] s = new String[10];
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout6);
for (int i = 0; i < 10; i++) {
s[i] = "ROW " + String.valueOf(i + 1);
}
lv = (ListView) findViewById(R.id.lv);
customAdapter = new CustomAdapter(MnnnnnnnActivity.this, s);
lv.setAdapter(customAdapter);
}
public int getScreenHeight() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
}
2) CustomAdapter.class:--------
public class CustomAdapter extends ArrayAdapter<String> {
private String[] s;
private WeakReference<MnnnnnnnActivity> mActivity;
public CustomAdapter(MnnnnnnnActivity activity1, String[] s) {
super(activity1.getApplicationContext(), R.layout.list_view_item, s);
this.s = s;
mActivity = new WeakReference<MnnnnnnnActivity>(activity1);
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(mActivity != null) {
MnnnnnnnActivity activity = mActivity.get();
if (activity != null) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(activity);
convertView = inflater.inflate(R.layout.list_view_item, null);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(s[position]);
holder.tv.setHeight(activity.getScreenHeight());
}
}
return convertView;
}
private class ViewHolder {
TextView tv;
}
}
3) layout6.xml:-----------
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv">
</ListView>
</android.support.constraint.ConstraintLayout>
4) list_view_item.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">
<TextView
android:id="#+id/tv"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="-"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold">
</TextView>
</LinearLayout>
5) Note: Although this is tested on phone, the same idea can be used to achieve something similar on a wareable. Also, a better approach would be to set the height of the linearLayout (which contains the textView) to the screen height.
6) Output:

Multiple clickable items with different actions to perform in ListFragment from SQLite

I'm a beginner.
I've a ListFragment where every element in the list contains three TextView and two different Buttons. Reading data from SQLite Database. Something like this:
ListFragment
--------------------
[Person Name]
[Person Phone]
[Person e-mail]
[Button 1][Button 2]
--------------------
[Person Name]
[Person Phone]
[Person e-mail]
[Button 1][Button 2]
--------------------
... (and so on) ...
where the button 1 will make a call and the 2 button will send an email to person.
detail, these buttons are clickable ImageView.
the Database is already pre-populated.
I iniciate my code like this:
#SuppressWarnings("deprecation")
public class Fragment01person extends ListFragment {
SQLiteDatabase dataBase = null;
Cursor crs;
SimpleCursorAdapter dataAdapter;
ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment01person, container,false);
dataBase = getActivity().openOrCreateDatabase("DBperson.db",
android.content.Context.MODE_PRIVATE, null);
crs = dataBase.rawQuery("SELECT * FROM person", null);
String[] columns = new String[] {
"person_name",
"person_phone",
"person_email"
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.text01person,
R.id.text02person,
R.id.text03person
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
getActivity(), R.layout.fragment01itemlist,
crs,
columns,
to);
listView = (ListView) rootView.findViewById(android.R.id.list);
View v = new View(getActivity());
listView.addHeaderView(v);
listView.addFooterView(v);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
rootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT ));
return rootView;
}
public void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Cursor cursorLocal = (Cursor) l.getItemAtPosition(position);
String nameperson = cursorLocal.getString(cursorLocal.getColumnIndex("person_name"));
String endperson = cursorLocal.getString(cursorLocal.getColumnIndex("person_endereco"));
String phoneperson = cursorLocal.getString(cursorLocal.getColumnIndex("person_phone"));
String emailperson = cursorLocal.getString(cursorLocal.getColumnIndex("person_email"));
showMessage("test",nameperson+" "+endperson+" "+phoneperson+" "+emailperson);
}
public void showMessage (String title, String text){
AlertDialog.Builder message = new AlertDialog.Builder(getActivity());
message.setTitle(title);
message.setMessage(text);
message.setNeutralButton("Ok", null);
message.show();
}
}
this is my itemlist xml (fragment01itemlist.xml):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/itemlistPerson"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:descendantFocusability="beforeDescendants">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingRight="15dp"
android:descendantFocusability="afterDescendants">
<TextView
android:id="#+id/text01person"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/blue_light2"
android:textSize="18sp"
android:text= "test"
android:textStyle="bold|italic"
/>
<TextView
android:id="#+id/text02person"
android:layout_width="wrap_content"
android:text= "test"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/text03person"
android:layout_width="wrap_content"
android:text= "test"
android:layout_height="wrap_content"
android:textStyle="italic"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imgPhone"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="fill_parent"
android:src="#drawable/ic_action_call_tc_01"
android:scaleType="center"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="true"
/>
<ImageView
android:id="#+id/imgEmail"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="fill_parent"
android:src="#drawable/ic_action_new_email_tc"
android:scaleType="center"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="true"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
this is my listview xml (fragment01person.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#color/pink_very_light"
android:cacheColorHint="#android:color/transparent"
android:divider="#null"
android:dividerHeight="10dp"
android:footerDividersEnabled="true"
android:headerDividersEnabled="true"
android:listSelector="#android:color/transparent" >
</ListView>
</RelativeLayout>
I can display the list.
but I don't know how to implement the buttons!
I've read various materials, but none works.
please can anyone help with this?
For making the multiple clickables in your list row you have to include the below given code for the views/buttons in the XML:
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="true"
and for doing operation for single row you need to use custom adapters instead using SimpleCursorAdapter, here the example goes
public class CustomListAdapter extends BaseAdapter
{
private Context mContext;
String[] cursor;
public SMSListAdapter(Context context,String[] cur)
{
super();
mContext=context;
cursor=cur;
}
public int getCount()
{
// return the number of records in cursor
return cursor.length;
}
// getView method is called for each item of ListView
public View getView(int position, View view, ViewGroup parent)
{
// inflate the layout for each item of listView
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.listview_each_item, null);
// get the reference of textViews
TextView textViewConatctNumber=(TextView)view.findViewById(R.id.textViewSMSSender);
TextView textViewSMSBody=(TextView)view.findViewById(R.id.textViewMessageBody);
Button bt1=(Button)view.findViewById(R.id.btn1);
bt1.setOnClickListner(new OnClickListener() {
#Override
public void onClick(View view) {
}
});
// Set the Sender number and smsBody to respective TextViews
textViewConatctNumber.setText(senderNumber);
textViewSMSBody.setText(smsBody);
return view;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}

I converted a fragment to a dialog and now text colors have changed

This is my first app. I had been setting a preference in an activity (with a fragment), but I want to move the fragment to a DialogPreference. It migrated okay, except my text colors have gone weird. See picture. The text should just be black, not white and gray. Any idea what I got wrong?
(Sorry, I know this is pretty sloppy code)
How it looks now:
My xml...
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relLay_dialog_semester_root"
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" >
<TextView
android:id="#+id/select_semester_prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/select_semester_prompt" />
<LinearLayout
android:id="#+id/linLayGradeSum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/select_semester_prompt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp" >
<Spinner
android:id="#+id/semester_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:hint="#string/hint_editSemester" />
<Spinner
android:id="#+id/year_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4" />
</LinearLayout>
<TextView
android:id="#+id/active_semesters_str"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/linLayGradeSum"
android:layout_below="#+id/linLayGradeSum"
android:text="#string/active_semester_str"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="#+id/active_semesters_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/active_semesters_str"
android:layout_below="#+id/active_semesters_str"
android:layout_marginTop="10dp"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
My extended DialogPreference class
public class SemesterDialogPreference extends DialogPreference {
SharedPreferences settings;
public static int YEAR_DEFAULT_VALUE = Activity_AddCourse.thisYear - Activity_AddCourse.baseYear;
public static int SEASON_DEFAULT_VALUE = Semester.getDefaultSemester().getSeasonInt();
public static int SEMESTER_DEFAULT_ID = 1;
String semester_id_key;
DBAdapter db;
// this is where I do everything view-related
#Override
public void onBindDialogView(View view){
settings = getSharedPreferences();
int curSemesterId = settings.getInt(semester_id_key, 1);
db = new DBAdapter(this.getContext().getApplicationContext());
db.open();
Semester curSemester = db.getSemester(curSemesterId);
db.close();
ArrayList<String> years = new ArrayList<String>();
for (int i = Activity_AddCourse.baseYear; i <= Activity_AddCourse.maxYear; i++)
{
years.add(Integer.toString(i));
}
ArrayAdapter<String> adapter_year = new ArrayAdapter<String>(this.getContext().getApplicationContext(),
android.R.layout.simple_spinner_item, years);
Spinner spinYear = (Spinner)view.findViewById(R.id.year_spinner);
adapter_year.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinYear.setAdapter(adapter_year);
spinYear.setSelection(curSemester.getYear() - Activity_AddCourse.baseYear);
Spinner spinner = (Spinner) view.findViewById(R.id.semester_spinner);
ArrayAdapter<CharSequence> adapter_spinner = ArrayAdapter.createFromResource(this.getContext().getApplicationContext(),
R.array.semester_spinner, android.R.layout.simple_spinner_item);
adapter_spinner.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter_spinner);
spinner.setSelection(Semester.seasonStringToInt(curSemester.getSeason()));
db = new DBAdapter(this.getContext().getApplicationContext());
db.open();
Semester[] s = db.getAllSemesters();
db.close();
String activeSem;
LinearLayout semesterList = (LinearLayout) view.findViewById(R.id.active_semesters_list);
if(s != null){
for(int i = 0; i < s.length; i++){
activeSem = s[i].getSemesterString();
TextView tv = (TextView) new TextView(this.getContext().getApplicationContext());
tv.setText(activeSem);
semesterList.addView(tv);
System.out.println(s[i].getSemesterString());
}
}
super.onBindDialogView(view);
}
public SemesterDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.dialog_set_semester);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
persistBoolean(positiveResult);
}
}
UPDATE:
The DialogPreference pops up from my settings activity, as shown below.
public class SettingsActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
Also, I was able to get the spinner text to black by making my own xml layouts for them, just as Huy Tran suggested. However, I had to make one for each the spinner_item and the spinner_dropdown_item. See below.
ArrayAdapter<String> adapter_year = new ArrayAdapter<String>(this.getContext().getApplicationContext(),
R.layout.my_spinner_item, years);
Spinner spinYear = (Spinner)view.findViewById(R.id.year_spinner);
adapter_year.setDropDownViewResource(R.layout.my_spinner_dropdown_item);
Why did I have to do this? I don't know. Also, dropdown items are each now about 50% taller. I copied exactly from source code into my own xml and it still renders differently. Very weird.
Create a layout like below and use that layout in setDropDownViewResource instead of android.R.layout.simple_spinner_dropdown_item.
Create my_spinner_dropdown_item.xml in res/layout:
EDITED:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textColor="#color/black"
/>
my_spinner_item
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />
Try using margin to change the size of each item.
And then in your SemesterDialogPreference:
setDropDownViewResource(R.layout.my_spinner_dropdown_item);

Change dynamically sub layout on radio selection

Sorry if I ask silly question, but so far had no luck in figuring out this one. I have form with 2 radio buttons that decide layout and used components of layout bellow them. Here is one of the layouts
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/arrival_date_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/arrival_date_label"/>
<EditText
android:id="#+id/arrival_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/arrival_date_label"
android:hint="10/05/2012"/>
<Spinner
android:id="#+id/arrival_time_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/arrival_date"/>
<TextView
android:id="#+id/return_date_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/return_date_label"
android:layout_below="#id/arrival_time_spinner"/>
<EditText
android:id="#+id/return_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/return_date_label"
android:hint="10/05/2012"/>
<Spinner
android:id="#+id/return_time_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/return_date"/>
</RelativeLayout>
and Java class to initialize some of the components used
public class ReturnFixedDays extends RelativeLayout {
private EditText arrivalDate;
private Spinner arrivalTime;
private EditText returnDate;
private Spinner returnTime;
private final String pattern = "dd/MM/yyyy";
public ReturnFixedDays(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.return_fixed_days, null);
arrivalDate = (EditText) view.findViewById(R.id.arrival_date);
arrivalDate.setText(arrivalDate());
arrivalTime = (Spinner) view.findViewById(R.id.arrival_time_spinner);
ArrayAdapter adapter = new ArrayAdapter(context, R.array.travel_time_entries,android.R.layout.simple_spinner_item);
arrivalTime.setAdapter(adapter);
returnDate = (EditText) view.findViewById(R.id.return_date);
returnDate.setText(returnDate());
returnTime = (Spinner) view.findViewById(R.id.return_time_spinner);
ArrayAdapter adapter2 = new ArrayAdapter(context, R.array.travel_time_entries,android.R.layout.simple_spinner_item);
returnTime.setAdapter(adapter2);
}
private String arrivalDate(){
return dateToString(today());
}
private String returnDate(){
return dateToString(weekLater());
}
private String dateToString(Date date){
return formatter().format(date);
}
private SimpleDateFormat formatter(){
return new SimpleDateFormat(pattern);
}
private Date weekLater(){
return adjustDateBy(today(), 7);
}
private Date today(){
return Calendar.getInstance().getTime();
}
private Date adjustDateBy(Date currentDate, int numOfDays) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(currentDate);
calendar.add(Calendar.DATE, numOfDays);
return calendar.getTime();
}
}
Now to add this layout to view I do as following in xml
<RelativeLayout
android:id="#+id/dates_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/flight_layout">
<TextView
android:id="#+id/date_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/dates_label"
style="#style/Label"/>
<RadioGroup
android:id="#+id/dates_radio_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="#id/date_label">
<RadioButton
android:id="#+id/flexible_dates_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/flexible_dates_label"
style="#style/Label"/>
<RadioButton
android:id="#+id/fixed_dates_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="#string/fixed_dates_label"
style="#style/Label"/>
</RadioGroup>
</RelativeLayout>
<RelativeLayout
android:id="#+id/stub_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/dates_layout">
<com.flyweekend.android.date.view.ReturnFixedDays
android:id="#+id/return_fixed_days_stub"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout="#layout/return_fixed_days"/>
<com.flyweekend.android.date.view.ReturnFlexibleDays
android:id="#+id/return_flexible_days_stub"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout="#layout/return_flexible_days"/>
</RelativeLayout>
FlightView.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
context = getActivity();
dateTypeRadioGrp = dateTypeRadioGroup(view);
returnFixedDays = (RelativeLayout) view.findViewById(R.id.return_fixed_days_stub);
updateDatesVisibility();
return view;
}
private RadioGroup dateTypeRadioGroup(View view){
RadioGroup group = (RadioGroup)view.findViewById(R.id.dates_radio_group);
group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup radioGroup, int selected) {
if(selected == R.id.flexible_dates_radio){
Log.i(TAG, "Flexible dates selected");
updateDatesVisibility();
}else{
Log.i(TAG, "Fixed dates selected");
updateDatesVisibility();
}
}
});
return group;
}
private void updateDatesVisibility(){
if(dateTypeRadioGrp.getCheckedRadioButtonId() == R.id.fixed_dates_radio){
returnFixedDays.setVisibility(View.VISIBLE);
} else{
returnFixedDays.setVisibility(View.INVISIBLE);
}
}
However neither group is ever visible. I guess I need extra pair of eyes to spot where I'm going wrong in adding these layouts dynamically.
With this:
View view = inflater.inflate(R.layout.return_fixed_days, null);
you've just inflated a layout file, you didn't actually attached it to your custom view ReturnFixedDays. To attach that inflated layout to your custom view you have to pass this as the second parameter(representing the parent of the newly inflated view hierarchy):
View view = inflater.inflate(R.layout.return_fixed_days, this);
There could be other things wrong in your code, so check and see if this solves your problem.

Why is my custom SimpleCursorAdapter returning different reults when ListView is scrolling

I'm trying to implement a custom SimpleCursorAdapter in order to switch out layouts in a ListView but I'm getting very random results while scrolling.
My issue here is that when I scroll up and down, the ListView seemingly by random, mix up the layouts. For instance, a row can have the listview_item_row layout at first but when scrolling in and out of the screen it can be replaced by listview_item_reply_row and back again.
I can't say I've really understood how newView works. I have successfully been able to use bindView to determine if I'm to hide an image in the layout or not but new View is veiled in darkness to me about its implementation and why the list scrolling behaves the way it does.
My goal is to have a list with x amount of items. Depending on if the item is a reply or a new message I want to load a specific layout on that row. Depending on if the row has an image or not I want to show/hide the imageview in the row layout.
What I have omitted in the code are the imports and row layouts. I'm trying to implement this by using Fragments and SimpleCursorAdapter in the v4 support package. The row layouts for the ListFragment are visibly different but contain the same widgets.
The ListView layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text_feed_header_random"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:padding="4dp"
android:text="Allmänt"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#FFF" />
<!--
The frame layout is here since we will be showing either
the empty view or the list view.
-->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/text_feed_header_random"
android:layout_above="#+id/footer" >
<!--
Here is the list. Since we are using a ListActivity, we
have to call it "#android:id/list" so ListActivity will
find it
-->
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false" />
<!-- Here is the view to show if the list is emtpy -->
<TextView
android:id="#android:id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No items."
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>
<LinearLayout
android:id="#+id/footer"
style="#android:style/ButtonBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="#+id/button_random_post"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Gör ett inlägg!" />
<Button
android:id="#+id/button_random_refresh"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Refresh list!" />
</LinearLayout>
</RelativeLayout>
A condensed Fragment using the layout above:
public class RandomFragment extends ListFragment implements LOG {
private DatabaseHelper mDbHelper;
private KarenfeedCursorAdapter mAdapter;
private Cursor mCursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "RANDOMFRAGMENT START!");
mDbHelper = new DatabaseHelper(getActivity());
mDbHelper.open();
mDbHelper.setTable(Posts.TABLE_RANDOM_POSTS);
//TODO: Replace SimpleCursorAdapter with a FragmentList instead...
mCursor = mDbHelper.getAllPostsSortedCursor();
String[] columns = { Posts.COLUMN_ID, Posts.COLUMN_CREATED, Posts.COLUMN_USER, Posts.COLUMN_COMMENT };
int[] to = { R.id.imageItemPhoto, R.id.textItemDate, R.id.textItemUser, R.id.textItemComment };
int flags = 0;
mAdapter = new FeedCursorAdapter(getActivity(), R.layout.listview_item_row, mCursor, columns, to, flags);
this.setListAdapter(mAdapter);
initFeedList(); // This call in the end executes mCursor = mDbHelper.getAllPostsSorted(); mAdapter.changeCursor(mCursor); mAdapter.notifyDataSetChanged();
}
}
The SimpleCursorAdapter that the ListFragment connects to:
public class FeedCursorAdapter extends SimpleCursorAdapter implements LOG {
private Context mContext;
private int mLayout;
public FeedCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
// TODO Auto-generated constructor stub
mContext = context;
mLayout = layout;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View view;
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
Log.d(TAG, "id: " +id+ " parentId: " +parentId);
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
if(id == parentId) {
view = inflater.inflate(R.layout.listview_item_row, parent, false);
} else {
view = inflater.inflate(R.layout.listview_item_reply_row, parent, false);
}
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
Log.d(TAG, "bindView()");
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
String date = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_CREATED));
String user = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_USER));
String comment = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_COMMENT));
TextView dateView = (TextView) view.findViewById(R.id.textItemDate);
TextView userView = (TextView) view.findViewById(R.id.textItemUser);
TextView commentView = (TextView) view.findViewById(R.id.textItemComment);
ImageView imageView = (ImageView) view.findViewById(R.id.imageItemPhoto);
dateView.setText(date);
userView.setText(user);
commentView.setText(comment);
if(hasImage == 0) {
imageView.setVisibility(ImageView.GONE);
} else {
String bitmapPath = Environment.getExternalStorageDirectory().getPath() + "/feed/" + id + "_thumb.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath);
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
imageView.setImageDrawable(bitmapDrawable);
imageView.setVisibility(ImageView.VISIBLE);
}
}
}
after reading your question and the code i think you should know that whenever you scroll a listview up or down it communicates with the adapter to populate the new items that came in to focus and for the case of different row for different data you should make a arraylist that will contain the name or id of the items whose backgrounds are different and then you start making there background according to your need on every call to adapter.

Categories

Resources