الروبوت. أداة ديناميكية في شكل بطاقات تعتمد على StackView (شيء مثل Tinder)

محدث: القطعة لم تعد عربات التي تجرها الدواب ، تم إصلاح كل شيء

مرحبا بالجميع.

منذ شهر ، تم نشر مقال حول طلبي الأول للمحاسبة عن الشؤون المالية الشخصية والعائلية.

منذ ذلك الحين ، قمت بتغيير الاسم إلى "Budget & Shopping Cart" ووفقًا لذلك ، أضفت وظيفة تتيح لك إنشاء عربة تسوق بسرعة واستخدامها.

القطعة السلة



آلية إنشاء عربة تسوق بسيطة للغاية ومنطقية وبالتالي مريحة:
في شجرة الدليل

يمكنك تحديد عدة عناصر داخل الفئة والنقر فوق الزر "إضافة إلى السلة". يتم عرض هذه القائمة من المواقف مع فئة الجذر في شكل بطاقة القطعة. يمكن تكرار هذا الإجراء عدة مرات حسب الضرورة.

نتيجة لذلك ، قمنا بتجميع قوائم التسوق بشكل منطقي.
الجمال هو أنه يظهر على الفور في جميع أعضاء المجموعة ، أي خلقت أمي بطاقات ، وذهب أبي على طول الطريق واشترى كل شيء.
انقر على البطاقة ويفتح النموذج لإدخال المبلغ. نتيجة لذلك ، أدخل المبلغ ليس لكل عنصر ، ولكن بالنسبة للفئة الرئيسية ككل. أي الفكرة هي أننا نستخدم الفئات التفصيلية لخطة الشراء ، ويتم أخذ المبلغ في الاعتبار بشكل أكثر خشونة من قبل الفئة الأصل.


تطبيق

1. فئة الخدمة
public class StackWidgetService extends RemoteViewsService { @Override public void onCreate() { super.onCreate(); } @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { return new StackRemoteViewsFactory(this.getApplicationContext(), intent); } } 


2. فئة محول لبطاقة كومة
 public class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { private List<MoneyTransaction> mWidgetItems = new ArrayList<MoneyTransaction>(); private Context mContext; @Inject FirestoreRepository repository; public StackRemoteViewsFactory(Context context, Intent intent) { mContext = context; Injector.getApplicationComponent().inject(this); } public void onCreate() { } public void onDestroy() { // repository.getLiveOrders().removeObserver(observer); // In onDestroy() you should tear down anything that was setup for your data source, // eg. cursors, connections, etc. mWidgetItems.clear(); } public int getCount() { return mWidgetItems.size(); } public RemoteViews getViewAt(int position) { // position will always range from 0 to getCount() - 1. // We construct a remote views item based on our widget item xml file, and set the // text based on the position. RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_stack_orders_item); if(position < mWidgetItems.size()) { MoneyTransaction moneyTransaction = mWidgetItems.get(position); String dateStr = FormatTool.getDateStringShort(moneyTransaction.getDate()); rv.setTextViewText(R.id.tv_date, dateStr); rv.setTextViewText(R.id.tv_correspondent, moneyTransaction.getCategoryObject().getName()); rv.setTextViewText(R.id.tv_comment, moneyTransaction.getComment()); Date today = FormatTool.getStartOfPeriod(Calendar.getInstance().getTime(), Constants.PERIODICITY_DAY); Date date = FormatTool.getStartOfPeriod(moneyTransaction.getDate(), Constants.PERIODICITY_DAY); long days = TimeUnit.MILLISECONDS.toDays(today.getTime() - date.getTime()); if(days < 0) { rv.setInt(R.id.widget_item, "setBackgroundResource", R.drawable.blue_with_border); } else if(days == 0) { rv.setInt(R.id.widget_item, "setBackgroundResource", R.drawable.green_with_border); } else if(days == 1) { rv.setInt(R.id.widget_item, "setBackgroundResource", R.drawable.orange_with_border); } else { rv.setInt(R.id.widget_item, "setBackgroundResource", R.drawable.red_with_border); } // Next, we set a fill-intent which will be used to fill-in the pending intent template // which is set on the collection view in StackWidgetProvider. Bundle extras = new Bundle(); extras.putString(FirestoreTables.PATH, moneyTransaction.getPath()); Intent fillInIntent = new Intent(); fillInIntent.setAction(OrdersWidgetProvider.CLICK_ACTION); fillInIntent.putExtras(extras); rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); } // Return the remote views object. return rv; } public RemoteViews getLoadingView() { // You can create a custom loading view (for instance when getViewAt() is slow.) If you // return null here, you will get the default loading view. return null; } public int getViewTypeCount() { return 1; } public long getItemId(int position) { return position; } public boolean hasStableIds() { return true; } public void onDataSetChanged() { mWidgetItems = repository.getOrdersSync(); } } 


3. فئة مزود القطعة
        .       -  2 : -             ( onDataSetChanged     ) -        -        . public class OrdersWidgetProvider extends AppWidgetProvider { public static final String CLICK_ACTION = "click_action"; private Observer observer; @Inject FirestoreRepository repository; public OrdersWidgetProvider() { super(); Injector.getApplicationComponent().inject(this); } @Override public void onReceive(Context context, Intent intent) { if(CLICK_ACTION.equals(intent.getAction())) { String path = intent.getStringExtra(FirestoreTables.PATH); repository.getTransaction(path) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(transaction -> { if(transaction != null) { Intent launchIntent = new Intent(context, TransactionDetailActivity.class); launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); launchIntent.putExtra(Constants.TRANSACTION, transaction); context.startActivity(launchIntent); } }); } super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { LiveData<List<MoneyTransaction>> liveData = repository.getLiveOrders(); if(observer != null && liveData.hasActiveObservers()) { liveData.removeObserver(observer); } observer = (Observer<List<MoneyTransaction>>) moneyTransactions -> { repository.setOrders(moneyTransactions); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stack_view); }; liveData.observeForever(observer); // update each of the widgets with the remote adapter for (int i = 0; i < appWidgetIds.length; ++i) { // Here we setup the intent which points to the StackViewService which will // // provide the views for this collection. Intent intent = new Intent(context, StackWidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); // // When intents are compared, the extras are ignored, so we need to embed the extras // // into the data so that the extras will not be ignored. intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_stack_orders_layout); rv.setRemoteAdapter(R.id.stack_view, intent); // // // The empty view is displayed when the collection has no items. It should be a sibling // // of the collection view. rv.setEmptyView(R.id.stack_view, R.id.empty_view); // // Here we setup the a pending intent template. Individuals items of a collection // // cannot setup their own pending intents, instead, the collection as a whole can // // setup a pending intent template, and the individual items can set a fillInIntent // // to create unique before on an item to item basis. Intent intent1 = new Intent(context, OrdersWidgetProvider.class); intent1.setAction(CLICK_ACTION); intent1.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT); rv.setPendingIntentTemplate(R.id.stack_view, pendingIntent); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.stack_view); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDisabled(Context context) { super.onDisabled(context); repository.getLiveOrders().removeObserver(observer); } } 


4. تخطيط القطعة
 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <StackView android:id="@+id/stack_view" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:loopViews="true"/> <LinearLayout android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/round_light_button_switcher" android:orientation="vertical"> <ImageView android:layout_width="wrap_content" android:layout_height="200dp" android:layout_margin="2dp" android:src="@drawable/beans_horizontal"/> <TextView style="@style/PrimaryDarkBold26" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="20dp" android:layout_marginTop="-40dp" android:layout_marginRight="20dp" android:layout_marginBottom="20dp" android:gravity="bottom|center_horizontal" android:text="@string/empty_view_text" android:textStyle="bold"/> </LinearLayout> </FrameLayout> 


5. بطاقة العلامات
 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget_item" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_correspondent" style="@style/White20" android:layout_width="match_parent" android:layout_height="50dp" android:ellipsize="end" /> <LinearLayout style="@style/WhiteDividerStyle" android:layout_marginTop="4dp"/> <TextView android:id="@+id/tv_comment" style="@style/White18" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp" android:ellipsize="end" android:maxLines="20"/> <LinearLayout style="@style/WhiteDividerStyle"/> <TextView android:id="@+id/tv_date" style="@style/White18" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp"/> </LinearLayout> 


6. وصف مزود XML
 <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget_stack_orders_layout" android:minWidth="150dp" android:minHeight="200dp" android:previewImage="@drawable/widget"> </appwidget-provider> 

Source: https://habr.com/ru/post/ar452998/


All Articles