Java ExpandableListView作为ViewPager的子级
我正在写一个控制个人预算的应用程序。它现在的设计基本上是使用两个不同的可扩展列表视图,一个用于收入,另一个用于支出。用于设置收入/费用类别以及交易的膨胀对话框。应用程序将数据存储在SQLite数据库中 到目前为止,一切顺利。当我试图实施某种设计,按不同月份组织这些数据时,我的问题就来了。我考虑过ViewPager,因为我认为它是最接近这个实现的选项。我是Android开发的新手,所以不确定是否有更好的选项来实现这个功能 此视图的活动和片段如下所示: SummaryActivity.javaJava ExpandableListView作为ViewPager的子级,java,android,Java,Android,我正在写一个控制个人预算的应用程序。它现在的设计基本上是使用两个不同的可扩展列表视图,一个用于收入,另一个用于支出。用于设置收入/费用类别以及交易的膨胀对话框。应用程序将数据存储在SQLite数据库中 到目前为止,一切顺利。当我试图实施某种设计,按不同月份组织这些数据时,我的问题就来了。我考虑过ViewPager,因为我认为它是最接近这个实现的选项。我是Android开发的新手,所以不确定是否有更好的选项来实现这个功能 此视图的活动和片段如下所示: SummaryActivity.java im
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import com.robin.xbudget.database.TransactionBaseHelper;
import com.robin.xbudget.database.TransactionDbSchema;
import com.robin.xbudget.database.TransactionDbSchema.TransactionTable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SummaryActivity extends SingleFragmentActivity implements
NewCategoryIncome.NewCategoryActivityListener
, NewTransactionIncome.NewIncomeActivityListener
, NewCategoryExpense.NewCategoryActivityListener
, NewTransactionExpense.NewExpenseActivityListener
, SummaryFragment.SummaryFragmentActivityListener
, Statistics.StatisticsListener {
/**
* Constants
*/
private static final String TAG = "XSummaryActivity";
public static final String mSalaryKey = "salaryKey";
public static final String mCurrencyKey = "currencyKey";
/**
* Members
*/
private SQLiteDatabase mDatabase;
private Context mContext;
/**
* Incomes
*/
private List<String> listIncomesDataGroup;
private Map<String, List<Transaction>> listIncomesDataChild;
/**
* Expenses
*/
private List<String> listExpensesDataGroup;
private Map<String, List<Transaction>> listExpensesDataChild;
/**
* Expense Adapter
*/
private ExpandableListViewAdapter expandableExpensesListViewAdapter;
private ExpandableListViewAdapter expandableIncomesListViewAdapter;
/**
* Getters / Setters
*/
@Override
public List<String> getIncomesDataGroup() {
return listIncomesDataGroup;
}
@Override
public List<String> getExpensesDataGroup() {
return listExpensesDataGroup;
}
@Override
public Map<String, List<Transaction>> getExpensesDataChild() {
return listExpensesDataChild;
}
@Override
public ExpandableListViewAdapter getIncomesAdapter() {
return expandableIncomesListViewAdapter;
}
@Override
public ExpandableListViewAdapter getExpensesAdapter() {
return expandableExpensesListViewAdapter;
}
@Override
public double getTotalIncomes() {
double total = 0;
for (Map.Entry<String, List<Transaction>> set : listIncomesDataChild.entrySet()) {
for (Transaction t : set.getValue()) {
total += t.getQuantity();
}
}
Log.d(TAG, "Total of Income Transactions is: " + total);
return total;
}
@Override
public double getTotalExpenses() {
double total = 0;
for (Map.Entry<String, List<Transaction>> set : listExpensesDataChild.entrySet()) {
for (Transaction t : set.getValue()) {
total += t.getQuantity();
}
}
Log.d(TAG, "Total of Expense Transactions is: " + total);
return total;
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
protected Fragment createFragment() {
Log.d(TAG, "onCreateFragment() was called");
initObject();
return SummaryFragment.newInstance();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
Log.d(TAG, "onCreate() was called");
super.onCreate(savedInstanceState, persistentState);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public void initObject() {
Log.d(TAG, "initObject() was called");
//Starting the databases
mContext = getApplicationContext();
mDatabase = new TransactionBaseHelper(mContext).getWritableDatabase();
// initializing the list of groups
listIncomesDataGroup = new ArrayList<>();
listExpensesDataGroup = new ArrayList<>();
// initializing the list of child
listIncomesDataChild = new HashMap<>();
listExpensesDataChild = new HashMap<>();
// initializing the adapter object
expandableIncomesListViewAdapter = new ExpandableListViewAdapter(getApplicationContext(), listIncomesDataGroup, listIncomesDataChild);
expandableExpensesListViewAdapter = new ExpandableListViewAdapter(getApplicationContext(), listExpensesDataGroup, listExpensesDataChild);
updateCategories();
updateChilds();
}
/***
* Listeners - (Interface Implementations)
*/
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void insertIncome(Transaction transaction) {
//String value = transaction + " " + mCurrency;
listIncomesDataChild.get(transaction.getCategory()).add(transaction);
//updateChilds();
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void insertExpense(Transaction transaction) {
ContentValues values = getContentValues(transaction);
Log.d(TAG, "TRANSACTION TO INSERT IS: " + transaction);
mDatabase.insert(TransactionTable.mTransactionExpense, null, values);
updateChilds();
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void updateExpense(Transaction transaction) {
ContentValues values = getContentValues(transaction);
String mIdString = transaction.getId().toString();
mDatabase.update(TransactionTable.mTransactionExpense, values, TransactionTable.ChildCols.UUID + " = ?", new String[]{mIdString});
updateChilds();
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void deleteExpense(Transaction transaction) {
String mIdString = transaction.getId().toString();
Log.d(TAG, "mIdString is: " + mIdString);
Log.d(TAG, "rows deleted are: " + mDatabase.delete(TransactionDbSchema.TransactionTable.mTransactionExpense, TransactionTable.ChildCols.UUID + " = ?", new String[]{mIdString}));
updateChilds();
}
@Override
public void insertCategoryExpense(String category) {
if (category != null || !category.trim().isEmpty()) {
mDatabase.execSQL("INSERT INTO " + TransactionTable.mCategoryExpense + " ('category') " + "VALUES (" + "'" + category + "'" + ")");
updateCategories();
}
}
private ContentValues getContentValues(Transaction transaction) {
ContentValues values = new ContentValues();
values.put(TransactionTable.ChildCols.CATEGORY, transaction.getCategory());
values.put(TransactionTable.ChildCols.UUID, transaction.getId().toString());
values.put(TransactionTable.ChildCols.NAME, transaction.getName());
values.put(TransactionTable.ChildCols.QUANTITY, transaction.getQuantity());
values.put(TransactionTable.ChildCols.DATE, transaction.getDate().getTime());
return values;
}
public List<String> getCategoryByTable(String table) {
List<String> categories = new ArrayList<>();
String query = "SELECT * from " + TransactionTable.mCategoryExpense;
Cursor c = mDatabase.rawQuery(query, null);
if (c.moveToFirst()) {
while (!c.isAfterLast()) {
categories.add(c.getString(0));
c.moveToNext();
}
}
return categories;
}
private TransactionCursorWrapper queryTransactions(String table, String whereClause, String[] whereArgs) {
Cursor cursor = mDatabase.query(
table
,
null, // columns - null selects all columns
whereClause,
whereArgs,
null, // groupBy
null, // having
null // orderBy
);
return new TransactionCursorWrapper(cursor);
}
@Override
public List<Transaction> getTransactionsByTable(String table) {
List<Transaction> transactions = new ArrayList<>();
TransactionCursorWrapper cursor = queryTransactions(table, null, null);
try {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
if (!transactions.contains(cursor.getTransaction()))
transactions.add(cursor.getTransaction());
cursor.moveToNext();
}
} finally {
cursor.close();
}
return transactions;
}
@Override
public void updateCategories() {
List list = getCategoryByTable(TransactionTable.mCategoryExpense);
Log.d(TAG, "BEFORE: GROUP SIZE" + list.size());
listExpensesDataGroup.clear();
listExpensesDataGroup.addAll(list);
for (String category : listExpensesDataGroup)
if (!listExpensesDataChild.containsKey(category))
listExpensesDataChild.put(category, new ArrayList<Transaction>());
expandableExpensesListViewAdapter.notifyDataSetChanged();
}
@RequiresApi(api = Build.VERSION_CODES.N)
public void updateChilds() {
//Retrieve data from the DB
List<Transaction> transactionList = getTransactionsByTable(TransactionTable.mTransactionExpense);
//Clear lists inside the Map
for (Map.Entry<String, List<Transaction>> set : getExpensesDataChild().entrySet())
set.getValue().clear();
//Add the values to each List from the DB
for (Transaction transaction : transactionList) {
Log.d(TAG, "transaction.getCategory() value is: " + transaction.getCategory());
Log.d(TAG, "listener.getExpensesDataChild().get(transaction.getCategory())" + getExpensesDataChild().get(transaction.getCategory()));
listExpensesDataChild.get(transaction.getCategory()).add(transaction);
}
expandableExpensesListViewAdapter.notifyDataSetChanged();
/*
//Remove the category from the view if it has no data
//Working through a local List to avoid ConcurrentModificationException
List <String> localListExpensesDataGroup = new ArrayList<>();
if(!listExpensesDataGroup.isEmpty() || listExpensesDataGroup!=null)
{ for(String group:listExpensesDataGroup){
if(localListExpensesDataChild.containsKey(group)) {
localListExpensesDataGroup.add(group);
}
}
*/
}
}
package com.robin.xbudget;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ExpandableListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import java.util.List;
import java.util.Map;
public class SummaryFragment extends Fragment {
SummaryFragmentActivityListener listener;
Button newIncomeGroupBtn;
Button newExpenseGroupBtn;
Button newIncomeTransactionBtn;
Button newExpenseTransactionBtn;
/**
* Expandable views
*/
private ExpandableListView expandableIncomesListView;
private ExpandableListView expandableExpensesListView;
/**
* Static members / Constants
*/
private static final String TAG = "XSecondActivity";
public static SummaryFragment newInstance() {
return new SummaryFragment();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (SummaryFragmentActivityListener) context;
} catch (ClassCastException cce) {
throw new ClassCastException("class has to implement SummaryFragmentActivityListener");
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_summary, container, false);
Log.d(TAG, "getContext onCreateView es: " + getContext());
expandableIncomesListView = view.findViewById(R.id.expandableIncomingsListView);
expandableExpensesListView = view.findViewById(R.id.expandableExpensesListView);
newIncomeGroupBtn = (Button) view.findViewById(R.id.button_income_group);
newExpenseGroupBtn = (Button) view.findViewById(R.id.button_expense_group);
newIncomeTransactionBtn = (Button) view.findViewById(R.id.button_incoming);
newExpenseTransactionBtn = (Button) view.findViewById(R.id.button_expense_transaction);
// setting list adapter
expandableIncomesListView.setAdapter(listener.getIncomesAdapter());
expandableExpensesListView.setAdapter(listener.getExpensesAdapter());
initListeners();
return view;
}
/**
* method to initialize listeners of the views
*/
private void initListeners() {
expandableExpensesListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
//Log.d(TAG, "Group position is: " + groupPosition);
}
});
expandableIncomesListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
//Log.d(TAG, "Group INCOMINGS position is: " + groupPosition + " and Child posititon is: " + childPosition);
Transaction transaction = new Transaction();
transaction.getId();
Bundle bundle = new Bundle();
NewTransactionIncome incomeDialog = new NewTransactionIncome();
incomeDialog.show(getFragmentManager(), "Input new income");
return false;
}
});
expandableExpensesListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
NewTransactionExpense expenseDialog = new NewTransactionExpense();
Bundle bundle = new Bundle();
bundle.putSerializable(NewTransactionExpense.ARG_EXPENSE_ID, ((Transaction) listener.getExpensesAdapter().getChild(groupPosition, childPosition)).getId());
expenseDialog.setArguments(bundle);
expenseDialog.show(getFragmentManager(), "Input new income");
return false;
}
});
/**
* Initialize Button listeners
*/
newIncomeTransactionBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(@Nullable View v) {
NewTransactionIncome incomeDialog = new NewTransactionIncome();
}
});
newIncomeGroupBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NewCategoryIncome categoryIncomeDialog = new NewCategoryIncome();
categoryIncomeDialog.show(getFragmentManager(), "NewIncomeCategory");
}
});
newExpenseTransactionBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(@Nullable View v) {
NewTransactionExpense expenseDialog = new NewTransactionExpense();
Transaction transaction = new Transaction();
Bundle bundle = new Bundle();
bundle.putSerializable(NewTransactionExpense.ARG_EXPENSE_ID, transaction.getId());
//expenseDialog.setArguments(bundle);
expenseDialog.show(getFragmentManager(), "Input new expense");
}
});
newExpenseGroupBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NewCategoryExpense categoryExpenseDialog = new NewCategoryExpense();
categoryExpenseDialog.show(getFragmentManager(), "NewExpenseCategory");
}
});
}
public interface SummaryFragmentActivityListener {
List<Transaction> getTransactionsByTable(String table);
Map<String, List<Transaction>> getExpensesDataChild();
ExpandableListViewAdapter getIncomesAdapter();
ExpandableListViewAdapter getExpensesAdapter();
void updateCategories();
}
}
导入android.content.ContentValues;
导入android.content.Context;
导入android.database.Cursor;
导入android.database.sqlite.SQLiteDatabase;
导入android.os.Build;
导入android.os.Bundle;
导入android.os.PersistableBundle;
导入android.util.Log;
导入androidx.annotation.Nullable;
导入androidx.annotation.RequiresApi;
导入androidx.fragment.app.fragment;
导入com.robin.xbudget.database.TransactionBaseHelper;
导入com.robin.xbudget.database.TransactionDbSchema;
导入com.robin.xbudget.database.TransactionDbSchema.TransactionTable;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
公共类SummaryActivity扩展了SingleFragmentActivity实现
NewCategoryIncome.NewCategoryActivityListener
,NewTransactionIncome.NewIncomeActivityListener
,NewCategoryExpense.NewCategoryActivityListener
,NewTransactionExpense.NewExpenseActivityListener
,SummaryFragment.SummaryFragmentActivityListener
,统计学{
/**
*常数
*/
私有静态最终字符串TAG=“XSummaryActivity”;
公共静态最终字符串mSalaryKey=“salaryKey”;
公共静态最终字符串mCurrencyKey=“currencyKey”;
/**
*成员
*/
私有SQLITE数据库mDatabase;
私有上下文;
/**
*收入
*/
私有列表listIncomesDataGroup;
私有地图listIncomesDataChild;
/**
*费用
*/
私有列表listExpensesDataGroup;
私有地图listensesdatachild;
/**
*费用适配器
*/
私有可扩展ListViewAdapter可扩展费用ListViewAdapter;
私有ExpandableListViewAdapter ExpandableIncomeListViewAdapter;
/**
*能手/二传手
*/
@凌驾
公共列表getIncomesDataGroup(){
返回listIncomesDataGroup;
}
@凌驾
公共列表getExpensesDataGroup(){
返回listExpensesDataGroup;
}
@凌驾
公共地图GetExpenseSdatchild(){
返回ListExpenseSdatchild;
}
@凌驾
公共可扩展ListViewAdapter GetIncomeAdapter(){
返回ExpandableIncomeListViewAdapter;
}
@凌驾
public ExpandableListViewAdapter getExpensesAdapter(){
返回expandableExpensesListViewAdapter;
}
@凌驾
公共双getTotalIncomes(){
双倍合计=0;
对于(Map.Entry集:listIncomesDataChild.entrySet()){
对于(事务t:set.getValue()){
总计+=t.getQuantity();
}
}
Log.d(标签“收入交易总额为:“+总额”);
返回总数;
}
@凌驾
公共双getTotalExpenses(){
双倍合计=0;
对于(Map.Entry集:listExpensesDataChild.entrySet()){
对于(事务t:set.getValue()){
总计+=t.getQuantity();
}
}
Log.d(标签“费用交易总额为:”+总计);
返回总数;
}
@RequiresApi(api=Build.VERSION\u code.N)
@凌驾
受保护的片段createFragment(){
d(标记“onCreateFragment()被调用”);
initObject();
返回SummaryFragment.newInstance();
}
@凌驾
创建时的公共void(@Nullable Bundle savedInstanceState,@Nullable persistable Bundle persistentState){
d(标记“onCreate()被调用”);
super.onCreate(savedInstanceState、persistentState);
}
@RequiresApi(api=Build.VERSION\u code.N)
public void initObject(){
d(标记“initObject()被调用”);
//启动数据库
mContext=getApplicationContext();
mDatabase=newTransactionBaseHelper(mContext.getWritableDatabase();
//正在初始化组列表
listIncomesDataGroup=new ArrayList();
listExpensesDataGroup=new ArrayList();
//正在初始化子对象列表
listIncomesDataChild=新HashMap();
ListExpenseSdatchild=newHashMap();
//初始化适配器对象
expandableIncomesListViewAdapter=新的ExpandableListViewAdapter(getApplicationContext(),listIncomesDataGroup,listIncomesDataChild);
expandableExpensesListViewAdapter=新的ExpandableListViewAdapter(getApplicationContext(),listExpensesDataGroup,listExpensesDataChild);
updateCategories();
updateChilds();
}
/***
*侦听器-(接口实现)
*/
@RequiresApi(api=Build.VERSION\u code.N)
@凌驾
公共void insertIncome(事务处理){
//字符串值=事务+“”+mCurrency;
listIncomesDataChild.get(transaction.getCategory()).add(transaction);
//updateChilds();
}
@RequiresApi(api=Build.VERSION\u code.N)
@凌驾
公开作废插入费用(交易){
ContentValues=getContentValues(事务);
Log.d(标记“要插入的事务是:“+事务”);
mDatabase.insert(TransactionTable.mtTransactionExpense,null,值);
向上的