i have created a ticket reservation app in which following data will be saved about passenger.
1) passenger name
2) passenger phone number
3) city from which passenger will go
4) city to which passenger will go
my code is as follows
public class TicketReservationView extends Activity implements OnClickListener {
private static Database theDatabase;
private EditText etName,etContact;
private Spinner spFrom,spTo;
private Button bSave,bShowSms;
private SQLiteDatabase db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ticket_reservation_view);
etName = (EditText)findViewById(R.id.etPassengerName);
etContact = (EditText)findViewById(R.id.etContactNo);
spFrom = (Spinner)findViewById(R.id.spFrom);
spTo = (Spinner)findViewById(R.id.spTo);
bSave = (Button)findViewById(R.id.bSave);
bSave.setOnClickListener(this);
bShowSms = (Button)findViewById(R.id.bShowSms);
bShowSms.setOnClickListener(this);
db = theDatabase.getWritableDatabase();
theDatabase.insert_city_data(db);
db.close();
loadData();
private void loadData()
{
db=theDatabase.getReadableDatabase();
String[] cities=theDatabase.getCitiesData(db);
ArrayAdapter<String> fromAdapter = new ArrayAdapter<String>(TicketReservationView.this,android.R.layout.simple_spinner_item,cities);
fromAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spFrom.setAdapter(fromAdapter);
spTo.setAdapter(fromAdapter);
db.close();
}
private String[] fillData()
{
String[] data= new String[4];
data[0] = etName.getText().toString();
data[1] = etContact.getText().toString();
data[2] = (String)spFrom.getSelectedItem();
data[3] = (String)spTo.getSelectedItem();
return data;
}
switch(view.getId())
{
case R.id.bSave:
db = theDatabase.getReadableDatabase();
boolean isPassengerExist = theDatabase.getPassengerExistance(db,etContact.getText().toString());
db.close();
if(!isPassengerExist)
{
String[] data = fillData();
db = theDatabase.getWritableDatabase();
theDatabase.insert_ticket_data(data,db);
showToast("Data saved Successfully");
db.close();
}
else
{
Toast.makeText(getBaseContext(), "Already Exist!", Toast.LENGTH_LONG).show();
}
break;
now the problem is that if the FROM city and TO city are same, it should display a toast that CITY NAMES ARE SAME.
i have tried following code
if(spFrom.getSelectedItem().equals(spTo.getSelectedItem()))
{
toast: "city names are same"
}
but it does not work for me
Use this
if(spFrom.getSelectedItem().toString().equals(spTo.getSelectedItem().toString())){
Toast.makeText(this,"city names are same",Toast.LENGTH_LONG).show();
}
This will work
Related
`I'm trying to create a dependent spinner with data from sqlite on android studio. But the spinners isn't showing any content as intended. The Prefix is suppose to narrow down the selection for the Lotno and finally display the Plantation_name based on database SmartSawit.db. pls help :> (its been days)
Spinner spinnerPrefix, spinnerLotno, spinnerPlantation_name;
Context context;
database Database;
String prefixValue, lotnoValue, nameValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_daftar_pokok);
spinnerPrefix = findViewById(R.id.spinnerPrefix);
spinnerLotno = findViewById(R.id.spinnerLotno);
spinnerPlantation_name = findViewById(R.id.spinnerPlantation_name);
context = this;
Database = new database(this, "SmartSawit.db", 1);
try {
Database.CheckDB();
fillSpinner(context,spinnerPrefix, "registered_plantation", "prefix", "");
spinnerPrefix.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
prefixValue = parent.getItemAtPosition(position).toString();
fillSpinner(context,spinnerLotno,"registered_plantation","lotno","where prefix = '"+prefixValue+"'");
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinnerLotno.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
lotnoValue = parent.getItemAtPosition(position).toString();
fillSpinner(context,spinnerPlantation_name,"registered_plantation","plantation_name","where prefix = '"+prefixValue+"' and lotno ='"+lotnoValue+"'");
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}catch(Exception e){
e.printStackTrace();
}
}
#SuppressLint("Range")
private void fillSpinner (Context context, Spinner mSpinner,String table, String column, String where) {
SQLiteDatabase db = Database.OpenDatabase("registered_plantation.db");
ArrayList<String> mArray = new ArrayList<>();
Cursor cursor = db.rawQuery("Select distinct "+column+" from "+table+""+where, null);
while (cursor.moveToNext()){
mArray.add(cursor.getString(cursor.getColumnIndex(column)));
}
cursor.close();
db.close();
ArrayAdapter mAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item,mArray);
mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSpinner.setAdapter(mAdapter);
}
}
my databasehelper code:
private Context context;
private static final String DATABASE_NAME = "SmartSawit.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "registered_plantation";
//private static final String COLUMN_NO = "_no";
private static final String COLUMN_NAME = "plantation_name";
private static final String COLUMN_PREFIX = "prefix";
private static final String COLUMN_LOT_NUMBER = "lotno";
String DbPath;
Context mcontext;
String DbName;
public database(Context context, String name, int version) {
super(context, DATABASE_NAME, null, version);
this.context = context;
this.mcontext = context;
this.DbName = DATABASE_NAME;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.DbPath = context.getFilesDir() + "/database/";
}
}
#Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TABLE_NAME +
" (" + COLUMN_NAME + " TEXT PRIMARY KEY, " +
COLUMN_PREFIX + " TEXT, " +
COLUMN_LOT_NUMBER + " INTEGER);";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public void CheckDB(){
SQLiteDatabase checkDB = null;
String filePath = DbPath + DbName;
File file = new File(filePath);
if(file.isFile() && file.exists()){
Toast.makeText(mcontext, "already exist", Toast.LENGTH_SHORT).show();
} else {
CopyDatabase();
}
}
private void CopyDatabase(){
try {
InputStream ios = mcontext.getAssets().open(DbName);
File directory = new File(DbPath);
if(!directory.exists()){
directory.mkdirs();
}
OutputStream os = new FileOutputStream(DbPath + DbName);
byte[] buffer = new byte[1024];
int len;
while((len = ios.read(buffer)) >0) {
os.write(buffer,0, len);
}
os.flush();
ios.close();
os.close();
Log.d("CopyDb", "Databse Copied");
} catch (Exception e) {
e.printStackTrace();
}
}
void addLadang (String prefix, String namaLadang, int lotNo){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_PREFIX, prefix );
cv.put(COLUMN_NAME, namaLadang );
cv.put(COLUMN_LOT_NUMBER, lotNo );
long result = db.insert(TABLE_NAME,null, cv);
if (result == -1){
Toast.makeText(context, "FAILED", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "SUCCESSFULLY SAVED", Toast.LENGTH_SHORT).show();
}
}
Cursor readAllData(){
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = null;
if(db != null){
cursor = db.rawQuery(query, null);
}
return cursor;
}
public SQLiteDatabase OpenDatabase(String dbName){
String filePath = DbPath + dbName;
return SQLiteDatabase.openDatabase(filePath,null,0);
}
}
You have a number of issues (not actually with the spinners).
First you are trying to open a non-existent database. That is you are using the the table name not the database name in the fillSpinner method by using:-
SQLiteDatabase db = Database.OpenDatabase("registered_plantation.db");
i.e. the database name is SmartSawit.db not registered_plantation.db.
The following fixes that issue (SEE EMBEDDED COMMENTS):-
SQLiteDatabase db = Database.OpenDatabase(/*"registered_plantation.db"<<<<<<<<<<< TABLE NAME NOt DATABASE NAME so USED >>>>>>>>>>*/ database.DATABASE_NAME /*after making it public */);
You then have issues with missing spaces in the WHERE clauses again in the fillSpinner method (fixed using, again see comments):-
Cursor cursor = db.rawQuery("Select distinct "+column+" from "+table+" "/*<<<<<<<<<< ADDED SPACE*/+where, null);
Applying the above fixes and using a layout that has the 3 spinners side by side and with different coloured backgrounds and with an excessive height. And with the following data in the database (in the assets folder name SmartSawit.db):-
Then when first run:-
Clicking on the first spinner
i.e. A and B, the 2 prefixes are selected accordingly
Clicking on B and
i.e. as expected
and so on.
Additional
If you checked the log with your original code, even though it doesn't crash you could have spotted the issue e.g. the log would have included:-
2023-02-07 11:13:59.641 24792-24792/a.a.so75365360javasqlitespinners D/CopyDb: Databse Copied
2023-02-07 11:13:59.642 24792-24792/a.a.so75365360javasqlitespinners E/SQLiteLog: (14) cannot open file at line 36667 of [c255889bd9]
2023-02-07 11:13:59.642 24792-24792/a.a.so75365360javasqlitespinners E/SQLiteLog: (14) os_unix.c:36667: (2) open(/data/user/0/a.a.so75365360javasqlitespinners/files/database/registered_plantation.db) -
2023-02-07 11:13:59.643 24792-24792/a.a.so75365360javasqlitespinners E/SQLiteDatabase: Failed to open database '/data/user/0/a.a.so75365360javasqlitespinners/files/database/registered_plantation.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:211)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:195)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:503)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:204)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:196)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:880)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:865)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:766)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:714)
at a.a.so75365360javasqlitespinners.database.OpenDatabase(database.java:124)
at a.a.so75365360javasqlitespinners.MainActivity.fillSpinner(MainActivity.java:69)
at a.a.so75365360javasqlitespinners.MainActivity.onCreate(MainActivity.java:36)
So although the copy was successfully accomplished e.g. using Device Explorer you would something along the lines of:-
Thus it is easy to see that registered_plantation.db is not at the expected location but SmartSwait.db is.
In short. If using try/catch and things are not working as expected the Check the Log for what you expect to see in the log (e.g. looking for Database copied would have made it easy to see that things were not as expected as the error lines immediately follow that message).
Search Function
mSearchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.d("data", charSequence.toString());
}
#Override
public void onTextChanged(CharSequence charSequence2, int i, int i1, int i2) {
String select = "SELECT * FROM RECORD WHERE name LIKE '"+charSequence2+"%'";
Cursor cursor = mSQLiteHelper.getData(select);
mList.clear();
while(cursor.moveToNext()) {
int id = cursor.getInt(0);
String name = cursor.getString(1);
String phone = cursor.getString(2);
mList.add(new Model(id,name,phone));
}
mAdapter.notifyDataSetChanged();
}
#Override
public void afterTextChanged(Editable editable) {
}
});
Update: This is LongClickListener where I tap to updated and delete my inserted data
mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {
//Alert dialog to display options of update and delete
final CharSequence [] items = {"Update","Delete","Call"};
AlertDialog.Builder dialog = new AlertDialog.Builder(RecordListActivity.this);
dialog.setTitle("Choose an Action");
dialog.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if(i == 0){
//update
Cursor c = mSQLiteHelper.getData("SELECT id FROM RECORD");
ArrayList<Integer> arrID = new ArrayList<Integer>();
while(c.moveToNext() ){
arrID.add(c.getInt(0));
}
//Show update Dialog
showDialogUpdate(RecordListActivity.this,arrID.get(position));
}
if(i==1){
//delete
Cursor c = mSQLiteHelper.getData("SELECT id FROM RECORD");
ArrayList<Integer> arrID = new ArrayList<Integer>();
while(c.moveToNext()){
arrID.add(c.getInt(0));
}
showDialogDelete(arrID.get(position));
}
//Call try
if(i==2){
TextView tvPhone = view.findViewById(R.id.textphone);
String phone = tvPhone.getText().toString();
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phone));
getBaseContext().startActivity(intent);
}
}
});
dialog.show();
return true;
}
});
Model: This is the Model
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
DataBase
public void updateData(String name, String phone, int id){
SQLiteDatabase database = this.getWritableDatabase();
//Query to update record
String sql = "UPDATE RECORD SET name=? , phone=? WHERE id=?";
SQLiteStatement statement = database.compileStatement(sql);
statement.bindString(1,name);
statement.bindString(2,phone);
statement.bindDouble(3,(double)id);
statement.execute();
database.close();
}
//Delete Data
public void deleteData(int id){
SQLiteDatabase database = this.getWritableDatabase();
//query to delete record using id
String sql = "DELETE FROM RECORD WHERE id=?";
SQLiteStatement statement = database.compileStatement(sql);
statement.clearBindings();
statement.bindDouble(1,(double)id);
statement.execute();
database.close();
}
//Getting Data
public Cursor getData(String sql){
SQLiteDatabase database = this.getReadableDatabase();
return database.rawQuery(sql,null);
}
Dialog
//DeleteDialog
private void showDialogDelete(final int idRecord) {
AlertDialog.Builder dialogDelete =new AlertDialog.Builder(RecordListActivity.this);
dialogDelete.setTitle("Warning!!");
dialogDelete.setMessage("Are you sure you want to delete this?");
dialogDelete.setPositiveButton("OK", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialogInterface, int i) {
try{
mSQLiteHelper.deleteData(idRecord);
Toast.makeText(getApplicationContext(), "Delete Successfully", Toast.LENGTH_SHORT).show();
}catch (Exception error){
Log.e("Delete error",error.getMessage());
}
}
});
dialogDelete.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
dialogDelete.show();
}
//UpdateDialog
private void showDialogUpdate(Activity activity, int position){
Dialog dialog = new Dialog(activity);
dialog.setContentView(R.layout.update_dialog);
dialog.setTitle("Update");
final EditText updateNameId = dialog.findViewById(R.id.updateNameId);
final EditText updatePhoneId = dialog.findViewById(R.id.updatePhoneId);
final Button updatebuttonId = dialog.findViewById(R.id.updatebuttonId);
//get Data Row Clicked from SQLite
Cursor cursor = mSQLiteHelper.getData("SELECT * FROM RECORD WHERE id="+position);
mList.clear();
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
updateNameId.setText(name);
String phone = cursor.getString(2);
updatePhoneId.setText(phone);
mList.add(new Model(id,name,phone));
}
//set width of dialog
int width = (int)(activity.getResources().getDisplayMetrics().widthPixels * 0.95);
//set height of dialog
int height = (int)(activity.getResources().getDisplayMetrics().heightPixels * 0.7);
dialog.getWindow().setLayout(width,height);
dialog.show();
updatebuttonId.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
try{
mSQLiteHelper.updateData(
updateNameId.getText().toString().trim(),
updatePhoneId.getText().toString().trim(),
position);
dialog.dismiss();
Toast.makeText(getApplicationContext(), "Updated", Toast.LENGTH_SHORT).show();
}catch(Exception error){
Log.e("Update error",error.getMessage());
}
updateRecorderList();
}
});
}
private void updateRecorderList() {
//get all data from SQLite
Cursor cursor = mSQLiteHelper.getData("SELECT * FROM RECORD");
mList.clear();
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
String phone = cursor.getString(2);
mList.add(new Model(id,name,phone));
}
mAdapter.notifyDataSetChanged();
}
When I search any data in the search bar It shows me the searched data but when I click to update it, it shows me the first row data to update, and also when I click to delete it shows me the first row to delete, where is my wrong logic can you enlighten me? anyone
You took the ID incorrectly, because you used a position that was always changing and cannot be correlated with the data.
You do not have to go to the database for the ID, as you already have it:
if (i == 0) {
//update
int contactId = mList.get(position).getId();
showDialogUpdate(RecordListActivity.this, contactId);
}
if (i == 1) {
//delete
int contactId = mList.get(position).getId();
showDialogDelete(contactId);
}
When i search it should only search first five characters from the array,
this is an app for finding dreams meaning, its like a dictionary app.
I added 2 listviews, and using a searchview to filter the results. but when i use searchview its searching the whole content in the array, and listing the result based on it which cause wrong results.
if i could search only the first five characters from these arrays, it will help me to get right results.
this is how i get the data from database
listView2 = findViewById(R.id.listView2);
sr_txt = findViewById(R.id.sr_txt);
listView = findViewById(R.id.listView);
databaseReference = FirebaseDatabase.getInstance().getReference("dreamapp");
dream1 = new Dream();
title_list = new ArrayList<>();
answer_list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<>(this, R.layout.item, R.id.item, title_list);
arrayAdapter2 = new ArrayAdapter<>(this, R.layout.item2, R.id.item2, answer_list);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot d : snapshot.getChildren()) {
dream1 = d.getValue(Dream.class);
title_list.add(dream1.getTitle());
answer_list.add(dream1.getAnswer());
}
listView.setAdapter(arrayAdapter);
listView2.setAdapter(arrayAdapter2);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int i, long id) {
Intent intent = new Intent(MainActivity.this, answer.class);
// String q = answer_list.get(i);
// String p =answer_list.get(i);
String q = (String) arrayAdapter2.getItem(i);
intent.putExtra("answer", q);
startActivity(intent);
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
this is my searchview.
sr_txt.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
MainActivity.this.arrayAdapter.getFilter().filter(query);
MainActivity.this.arrayAdapter2.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
MainActivity.this.arrayAdapter.getFilter().filter(newText);
MainActivity.this.arrayAdapter2.getFilter().filter(newText);
return false;
}
});
Please give more detail of what you want.It would be more clear if you dont mind uploading image of what you are getting and what you want.
I need to delete the item from database and ListView. I can delete the item from ListView but i can't delete it from database. I think the problem is in getting the position of the item from the database i tried to do it in my own but it does not work. I don't know what should I do.Help me to slove this.
myDB = new DbHandler(this);
userList = new ArrayList<>();
data = myDB.getListContents();
numRows = data.getCount();
if (numRows == 0) {
Toast.makeText(AddCount.this, "No Items", Toast.LENGTH_LONG).show();
} else {
while (data.moveToNext()) {
user = new User(data.getString(1), data.getString(2));
userList.add(user);
}
}
adapter = new Two_columnListAdapter(this, R.layout.list_item_layout, userList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(final AdapterView<?> arg0, View arg1, final int arg2, final long arg3) {
final AlertDialog.Builder delete = new AlertDialog.Builder(AddCount.this);
delete.setIcon(R.drawable.ic_baseline_delete_24);
delete.setTitle("Are you sure");
delete.setMessage("Do you want to delete this item?");
delete.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
DbHandler db = new DbHandler(getApplicationContext());
myDB.deleteData(userList.get(arg2));
userList.remove(arg2);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), "Deleted" ,Toast.LENGTH_SHORT).show();
}
});`
`Two_columnAdapter.java
public class Two_columnListAdapter extends ArrayAdapter<User> {
private LayoutInflater layoutInflater;
private ArrayList<User>users;
private int mviewResourceId;
public Two_columnListAdapter(Context context,int textViewResourceId,ArrayList<User>users){
super(context,textViewResourceId,users);
this.users = users;
layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mviewResourceId = textViewResourceId;
}
public View getView(int position, View convertView, ViewGroup parents){
convertView = layoutInflater.inflate(mviewResourceId,null);
User user= users.get(position);
if (user != null){
TextView text = (TextView)convertView.findViewById(R.id.title);
TextView num = (TextView)convertView.findViewById(R.id.value);
if (text != null){
text.setText(user.getText());
}
if (num != null){
num.setText(user.getNum());
}
}
return convertView;
}
DatabaseHelpher(delete the single row from database)
public void deleteData(String id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_Inputs, KEY_ID + " =?", new String[]{id});
db.close();
}
You can save the return data inside a model class instead of a list. Then call the setOnLongClickListener in your adapter class, inside onBindViewHolder.
class listHolder extends RecyclerView.ViewHolder{
private View view;
public listHolder(#NonNull View itemView) {
super(itemView);
view = itemView;
}
}
#Override
public void onBindViewHolder(#NonNull listHolder listHolder, int position, #NonNull userModel userModel) {
viewHolder.view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// Do somethings....
}
});
For more info you can check out this link, Hope this helps!
Senior Geeks.
I'd like to request a simple but fully working example of how to implement an ExpandableListView while extending from BaseExpandableListAdapter Yet Reading data from an Sqlite Database.
I have researched and experimented on the question (see here), but with minimal success where i was able to display some data in the header, albeit it was same values repeating for all group headers. Also child items don't show.
The reason for extending with BaseExpandableListAdapter is to have a custom layout for the group header. The reason for SQLite access is naturally because thats where my data is stored.
All examples trawled on the net so far use either SimpleCursorTreeAdapter or CursorTreeAdapter as the extender in DB based applications or simply BaseExpandableListAdapter when data used is in ArrayLists.
Below is the Experimentation thus far. (with this code,only the group header is populated with the same figures over and over. Childitems dont appear)
public class ExpandableListViewAdapterCustom extends BaseExpandableListAdapter {
protected Activity currentActivity;
public ExpandableListViewAdapterCustom(Activity callingActivity){
this.currentActivity = callingActivity;
}
private Cursor mGroupsCursorLocal ;
private Cursor mChildCursor;
private Context ctx;
private int groupItem;
private int childItem;
private String[] fieldsToUseFromGroupCursor;
private int[] screenTextsToMapGroupDataTo;
private String[] fieldsToUseFromChildCursor;
private int[] screenTextsToMapChildDataTo;
public ArrayList<String> tempChild;
public LayoutInflater minflater;
public Activity activity;
public int intGroupTotal;
public void setCurrentActivity(Activity activity) {
this.activity = activity;
}
public void setCtx(Context ctx) {
this.ctx = ctx;
}
public void setGroupItem(int groupItem) {
this.groupItem = groupItem;
}
public void setChildItem(int childItem) {
this.childItem = childItem;
}
public Activity getCurrentActivity() {
return currentActivity;
}
public Cursor getmGroupsCursorLocal() {
return mGroupsCursorLocal;
}
public Context getCtx() {
return currentActivity.getBaseContext();
}
public void setmGroupsCursorLocal(Cursor mGroupsCursor) {
this.mGroupsCursorLocal = mGroupsCursor;
}
public ExpandableListViewAdapterCustom(Cursor mGroupsCursor,
Activity activity,
int groupItem,
int childItem,
String[] fieldsToUseFromGroupCursor,
int[] screenTextsToMapGroupDataTo,
String[] fieldsToUseFromChildCursor,
int[] screenTextsToMapChildDataTo) {
DatabaseRoutines db = new DatabaseRoutines(activity);
setmGroupsCursorLocal(mGroupsCursor);
mGroupsCursorLocal = db.fetchGroup();
activity.startManagingCursor (mGroupsCursor);
mGroupsCursorLocal.moveToFirst();
mChildCursor=db.fetchChildren(mGroupsCursorLocal.getColumnIndex("Year"));
mChildCursor.moveToFirst();
activity.startManagingCursor(mChildCursor);
setCtx(activity);
setCurrentActivity(activity);
}
public void setInflater(LayoutInflater mInflater, Activity act) {
this.minflater = mInflater;
activity = act;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
#Override
public View getChildView(int groupPosition,
int childPosition,boolean
isLastChild,
View convertView,
ViewGroup parent) {
View v = convertView;
if (v == null)
{
LayoutInflater inflater =
(LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.exp_listview_childrow, parent, false);
}
TextView txtMonth = (TextView) v.findViewById(R.id.txtMonth);
TextView txtMonthAmountSent = (TextView)
v.findViewById(R.id.txtMonthAmountSentValue);
TextView txtMonthReceived = (TextView)
v.findViewById(R.id.txtMonthAmountReceivedValue);
txtMonth.setText(mChildCursor.getString(mChildCursor.getColumnIndex("Month")));
txtMonthAmountSent.setText
(mChildCursor.getString(mChildCursor.getColumnIndex("TotalSent")));
txtMonthReceived.setText
(mChildCursor.getString(mChildCursor.getColumnIndex("TotalReceived")));
return v;
}
#Override
public int getChildrenCount(int groupPosition) {
return (mChildCursor.getCount());
}
#Override
public Object getGroup(int groupPosition) {
return null;
}
#Override
public int getGroupCount() {
return mGroupsCursorLocal.getCount();
}
#Override
public void onGroupCollapsed(int groupPosition) {
super.onGroupCollapsed(groupPosition);
}
#Override
public void onGroupExpanded(int groupPosition) {
super.onGroupExpanded(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public View getGroupView(
int groupPosition,
boolean isExpanded,
View convertView,
ViewGroup parent)
{
View v = convertView;
if (v == null) {
LayoutInflater inflater =
(LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.exp_listview_groupheader, parent, false);
}
TextView txtYear = (TextView) v.findViewById(R.id.txtYearValue);
TextView txtAmountSent = (TextView) v.findViewById(R.id.txtAmountSentValue);
TextView txtAmountRecieved = (TextView)
v.findViewById(R.id.txtAmountReceivedValue);
txtYear.setText(mGroupsCursorLocal.getString(
mGroupsCursorLocal.getColumnIndex("Year")));
txtAmountSent.setText(
mGroupsCursorLocal.getString(mGroupsCursorLocal.getColumnIndex("TotalSent")));
txtAmountRecieved.setText(
GroupsCursorLocal.getString(mGroupsCursorLocal.getColumnIndex("TotalReceived")));
return v;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
}
The Database code is like this
public Cursor fetchGroup() {
SQLiteDatabase db = this.getReadableDatabase(); //if memory leaks check here
String query = "SELECT DISTINCT MIN(ID) AS id,
Year, SUM(SentAmount) AS TotalSent, SUM(ReceivedAmount) AS TotalReceived
FROM MyTbl GROUP BY Year ORDER BY Year DESC ";
return db.rawQuery(query, null);}
public Cursor fetchChildren(int Yr) {
SQLiteDatabase db = this.getReadableDatabase(); //if memory leaks check here
String query = "SELECT MIN(ID) AS id,
Year, Month, SUM(SentAmount) AS TotalSent,
SUM(ReceivedAmount) AS TotalReceived
FROM MyTbl Where Year= "+ Yr +" GROUP BY Year,
Month ORDER BY Year DESC, Month DESC";
return db.rawQuery(query, null);
}
The Code is called from main activity using the following
ExpandableListView elv = (ExpandableListView)
findViewById(R.id.expandableListView);
ExpandableListAdapter mAdapter = new
ExpandableListViewAdapterCustom(mGroupsCursor,
MyActivity.this,
R.layout.exp_listview_groupheader,// Your row layout for a group
R.layout.exp_listview_childrow, // Your row layout for a child
new String[] { "Year",
"TotalSent",
"TotalReceived" },// Field(s) to use from group cursor
new int[] {R.id.txtYearValue,
R.id.txtAmountSentValue,
R.id.txtAmountReceivedValue },// Widget ids to put group data
into new String[] { "Year","Month",
"TotalSent",
"TotalReceived" }, // Field(s) to use from child cursors new
int[] {R.id.txtMonthValue,
R.id.txtMonthAmountSentValue,
R.id.txtMonthAmountReceivedValue});// Widget ids to put child d
data into
elv.setClickable(true);
elv.setAdapter(mAdapter); // set the
After almost two weeks and no answer, i decided to simply use an ExpandableListView example using ArrayLists and modified it such that the ArrayLists were populated by data from the DB. Its not what i wanted but it works. I was actually suprised that nowhwere on the web is there an example of using ExpandableListview extended form BaseAdapter but reading from SQlite using say cursorTreeAdapter or SimpleCursorAdapter.
Below is how i did it in case it helps someone in future. the code shown is the bit that populates the ArrayList from DB
public ArrayList<ExpandListGroup> SetStandardGroups() {
ArrayList<ExpandListGroup> list = new ArrayList<ExpandListGroup>();
ArrayList<ExpandListChild> list2 = new ArrayList<ExpandListChild>();
int intMonthNum;
ExpandListGroup grp;
ExpandListChild chld;
//initialize db code here
DatabaseRoutines db = new DatabaseRoutines(this);
//create the Groups retreival cursor;
Cursor mGroupsCursor = db.fetchGroup();
//---the database call is done using this code which is in my
//---custom db class which implements the sqlhelper methods etc
//------start of db code snippet-------------------------------
//---public Cursor fetchGroup() {
//---SQLiteDatabase db = this.getReadableDatabase();
//--- String query = "SELECT DISTINCT MIN(ID) AS id, Year,
//--- SUM(SentAmount) AS TotalSent,
//--- SUM(ReceivedAmount) AS TotalReceived
//--- FROM Tbl GROUP BY Year ORDER BY Year DESC ";
//--- return db.rawQuery(query, null);}
//------end of db code snippet-------------------------------
mGroupsCursor.moveToFirst();
//method is depreciated from api14 but i'm targeting Gingerbread (api10) so i need to use it.
startManagingCursor(mGroupsCursor);
int intYear;
int intHeaderCounter = 0;
int intChildCounter = 0;
int intChildTotalCount = 0;
int intHeaderTotalGroupCount = mGroupsCursor.getCount();
//set the starting Year for the loop, if there is data;
if (intHeaderTotalGroupCount > 0) {
//get the first year
//intYear = mGroupsCursor.getInt(mGroupsCursor.getColumnIndex("Year"));
for (intHeaderCounter = 0; intHeaderCounter < intHeaderTotalGroupCount; intHeaderCounter++) {
grp = new ExpandListGroup();
intYear = mGroupsCursor.getInt(mGroupsCursor.getColumnIndex("Year"));
grp.setYear(intYear);
grp.setYearAmountReceived(mGroupsCursor.getDouble(mGroupsCursor.getColumnIndex("TotalReceived")));
grp.setYearAmountSent(mGroupsCursor.getDouble(mGroupsCursor.getColumnIndex("TotalSent")));
grp.setTag(mGroupsCursor.getString(mGroupsCursor.getColumnIndex("id")));
//Prepare counters for inner loop for child items of each
Cursor mChildCursor = db.fetchChildren(intYear);
mChildCursor.moveToFirst();
intChildTotalCount = mChildCursor.getCount();
//populate child items
for (intChildCounter = 0; intChildCounter < intChildTotalCount; intChildCounter++) {
chld = new ExpandListChild();
intMonthNum = mChildCursor.getInt(mChildCursor.getColumnIndex("Month"));
chld.setMonthNumber(intMonthNum);
chld.setTotalReceivedMonth(mChildCursor.getInt(mChildCursor.getColumnIndex("TotalReceived")));
chld.setTotalSentMonth(mChildCursor.getInt(mChildCursor.getColumnIndex("TotalSent")));
chld.setTag(mGroupsCursor.getString(mGroupsCursor.getColumnIndex("id")).toString());
list2.add(chld);
//grp.setItems(list2);
//move to next child record;
mChildCursor.moveToNext();
}
grp.setItems(list2);
list.add(grp);
list2 = new ArrayList<ExpandListChild>();
//move to next parent record;
mGroupsCursor.moveToNext();
}
} else {
log.d( "yourdebugtag_here", "Sorry, No Transactions Found.");
}
//db.close();
return list;
}