Good day. Implemented some kind of store. There is a template containing ImageView and two TextView . Data from the database is pushed into these View with the help of CursorLoader . When you click on View in the database, the product field is updated, which means that the product was purchased (zero or one). Up to this point, everything works well. How do I process the data when the store is loaded? It is necessary to do this: if a product has a unit in the database, then View not clickable.

 public class ShopActivity extends AppCompatActivity implements LoaderCallbacks<Cursor>{ SimpleCursorAdapter scAdapter; ListView lvData; DBHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shop2); dbHelper = new DBHelper(this); String[] from = new String[] { DBHelper.ITEMS_IMAGE, DBHelper.ITEMS_NAME, DBHelper.ITEMS_COST }; int[] to = new int[] { R.id.radioImageIV, R.id.radioDescriptionTV, R.id.radioCostTV}; scAdapter = new SimpleCursorAdapter(this, R.layout.shop_item_radio, null, from, to, 0); lvData = (ListView) findViewById(R.id.lvData); lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { view.setClickable(false); new ProgramManager(Shop2Activity.this).setBought(view); //обновляСт запись Π² Π‘Π” } }); lvData.setAdapter(scAdapter); getSupportLoaderManager().initLoader(0, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { return new MyCursorLoader(this, dbHelper); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { scAdapter.swapCursor(cursor); } static class MyCursorLoader extends CursorLoader { DBHelper dbHelper; public MyCursorLoader(Context context, DBHelper db) { super(context); this.dbHelper = db; } @Override public Cursor loadInBackground() { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.query(DBHelper.ITEMS_TABLE_NAME, null, null, null, null, null,null); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } return cursor; } } 

shop_item_radio.xml

 <android.support.constraint.ConstraintLayout 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:animateLayoutChanges="true" android:background="@drawable/border_shop" android:fillViewport="true" android:isScrollContainer="true"> <ImageView android:id="@+id/radioImageIV" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginBottom="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:background="@drawable/border" android:padding="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/radio" /> <TextView android:id="@+id/radioDescriptionTV" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="4dp" android:layout_marginTop="8dp" android:textAlignment="textStart" android:textColor="#004D40" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/radioImageIV" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/radioCostTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:drawableLeft="@drawable/ic_money_24dp" android:text="10000" android:textAlignment="gravity" android:textColor="#004D40" android:textSize="18sp" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/radioDescriptionTV" /> </android.support.constraint.ConstraintLayout> 
  • If you do not mind, share an example. All the examples I found contain deprecated methods - R1zen
  • Column isBought; Here is the entire SQL query for creating the database CREATE TABLE "items" ( "_id" INTEGER PRIMARY KEY AUTOINCREMENT, "itemName" TEXT, "itemDescriptions" TEXT, "itemCost" INTEGER, "itemImage" TEXT, "isBought" INTEGER ); - R1zen 2:42 pm
  • I insert the data into this template, I click on it to buy R.layout.shop_item_radio - R1zen
  • This is a separate xml file in which the elements are located . Added listing to the question - R1zen
  • Yes, the point is that the item cannot be bought more than 1 time - R1zen

2 answers 2

Approximately such an adapter, I don’t have the opportunity to test it, as you understand it, but the idea should be clear:

 public class ShopAdapter extends SimpleCursorAdapter { private Context mContext; private int layout; private Cursor cr; private final LayoutInflater inflater; public ShopAdapter(Context context, int layout, Cursor c, String[] from,int[] to, int flag) { super(context, layout, c, from, to, flag); this.layout=layout; this.mContext = context; this.inflater=LayoutInflater.from(context); this.cr=c; } @Override public View newView (Context context, Cursor cursor, ViewGroup parent) { return inflater.inflate(layout, null); } @Override public void bindView(View view, Context context, Cursor cursor) { super.bindView(view, context, cursor); ConstraintLayout item =(ConstraintLayout)view.findViewById(R.id.item); // здСсь вмСсто "isBought" ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ константу ΠΈΠ· ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚Π°, Ρ‚ΠΈΠΏΠ° DBHelper.IS_BOUGHT int column=cursor.getColumnIndexOrThrow("isBought"); item.setEnabled(cursor.getInt(column) != 1); // кликабСльно Ссли содСрТимоС ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π½Π΅ = 1 } } 

In the markup of the item, the root layout must be assigned an ID:

 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id = "@+id/item" ... > </android.support.constraint.ConstraintLayout> 

Activate using our adapter instead of the standard one:

 String[] from = new String[] { DBHelper.ITEMS_IMAGE, DBHelper.ITEMS_NAME, DBHelper.ITEMS_COST }; int[] to = new int[] { R.id.radioImageIV, R.id.radioDescriptionTV, R.id.radioCostTV}; scAdapter = new ShopAdapter(this, R.layout.shop_item_radio, null, from, to, 0); 
  • Thank you very much! Slightly corrected the adapter and it worked. Added a working listing to the question. - R1zen
  • one
    @ R1zen this line if (column == 1){ view.setClickable(false); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); if (column == 1){ view.setClickable(false); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); Must include explicit instructions for both options (what to display when it is 1 and when it is not 1), otherwise there will be chaos when scrolling in items: if (column == 1){ view.setClickable(false); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); } else { view.setClickable(true); cost.setText("НЕ ΠΊΡƒΠΏΠ»Π΅Π½ΠΎ");} if (column == 1){ view.setClickable(false); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); } else { view.setClickable(true); cost.setText("НЕ ΠΊΡƒΠΏΠ»Π΅Π½ΠΎ");} if (column == 1){ view.setClickable(false); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); } else { view.setClickable(true); cost.setText("НЕ ΠΊΡƒΠΏΠ»Π΅Π½ΠΎ");} - pavlofff
  • else { view.setClickable(true); } else { view.setClickable(true); } I did it like this. After all, the data for cost initially comes from String[] from = new String[] { DBHelper.ITEMS_IMAGE, DBHelper.ITEMS_NAME, DBHelper.ITEMS_COST}; int[] to = new int[] { R.id.radioImageIV, R.id.radioDescriptionTV, R.id.radioCostTV}; String[] from = new String[] { DBHelper.ITEMS_IMAGE, DBHelper.ITEMS_NAME, DBHelper.ITEMS_COST}; int[] to = new int[] { R.id.radioImageIV, R.id.radioDescriptionTV, R.id.radioCostTV}; - R1zen

I will leave here a working version of the adapter, maybe someone will come in handy. Thanks @pavlofff ShopAdapter.java

 public class ShopAdapter extends SimpleCursorAdapter implements View.OnClickListener{ private Context mContext; private int layout; private Cursor cr; private final LayoutInflater inflater; public ShopAdapter(Context context, int layout, Cursor c, String[] from,int[] to, int flag) { super(context, layout, c, from, to, flag); this.layout=layout; this.mContext = context; this.inflater=LayoutInflater.from(context); this.cr = c; } @Override public View newView (Context context, Cursor cursor, ViewGroup parent) { return inflater.inflate(layout, null); } @Override public void bindView(View view, Context context, Cursor cursor) { super.bindView(view, context, cursor); ConstraintLayout item = view.findViewById(R.id.item); item.setOnClickListener(this); TextView cost = view.findViewById(R.id.radioCostTV); int img = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.ITEMS_COST_ICON)); int column = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.ITEMS_IS_BOUGHT)); if (column == 1){ view.setClickable(false); // кликабСльно Ссли содСрТимоС ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π½Π΅ = 1 cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); //Ссли Ρ€Π°ΡΠΊΠΎΠΌΠ΅Π½Ρ‚ΠΈΡ‚ΡŒ строку Π½ΠΈΠΆΠ΅, Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ странно. ΠŸΡ€ΠΈ ΠΏΠΎΠΊΡƒΠΏΠΊΠ΅ любого ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚Π°, ΠΈΠΊΠΎΠ½ΠΊΠ° мСняСтся ΠΈ Ρƒ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ (ΠΏΡ€ΠΈ этом ΠΎΠ½ ΠΊΠ»ΠΈΠΊΠ°Π±Π΅Π»Π΅Π½). `ΠŸΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Ρ‚ΡΠ½ΡƒΡ‚ΡŒ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π‘Π”. //cost.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_check_circle_black_24dp, 0, 0, 0); } cost.setCompoundDrawablesWithIntrinsicBounds(img, 0, 0, 0); } else { view.setClickable(true); //cost.setText("НЕ ΠΊΡƒΠΏΠ»Π΅Π½ΠΎ"); } @Override public void onClick(View v) { //ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠΎΠ² ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π΄Π΅Π»Π°Ρ‚ΡŒ Π² Π°Π΄Π°ΠΏΡ‚Π΅Ρ€Π΅ TextView cost = v.findViewById(R.id.radioCostTV); if (GameActivity.hero.getMoney() >= Integer.parseInt(cost.getText().toString())) { new ProgramManager(mContext).setBought(v); cost.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_check_circle_black_24dp, 0, 0, 0); cost.setText("ΠšΡƒΠΏΠ»Π΅Π½ΠΎ"); v.setClickable(false); } else Toast.makeText(mContext, "no money", Toast.LENGTH_SHORT).show(); } } 
  • this is //cost.setText("НЕ ΠΊΡƒΠΏΠ»Π΅Π½ΠΎ"); need to uncomment and if no text is needed then set an empty string cost.setText(""); Otherwise, you will periodically appear "bought" where you did not expect it. In general, the studio must point to the code with the unreachable component, because you got it wrong in brackets and else does not apply to if - pavlofff
  • In order for the picture not to behave strangely, you need to also indicate both options, which should be in place of the picture, both in the if block and in the else block - pavlofff
  • Yes, it really helped. However, there was another problem. When you buy 1 item, its icon is updated, the text changes, all is well. You can exit the store screen, re-enter and everything will be fine. But if you buy an item, scroll down the ListView (so that the item disappears from view) and then scroll back up, the picture gets confused and returns to the old one, just like the text, and item is again clickable. Those. It is solved only by closing the activation. I understand you need to somehow update the data in the cursor? - R1zen
  • Yes of course. it is not enough to change the view on the screen, you need to save the new state in the database, and then update the cursor so that it has actual data, because you are building a list based on the cursor data. Keep in mind that what disappeared while scrolling from the screen and was not saved to permanent storage is destroyed. I would recommend that you look in the direction of livedata, livemodel and room - new Google tools, if you look into them, they greatly facilitate development - pavlofff
  • look at this answer , in general, there is everything in the code that you may need for proper implementation. and working with editable data and updating and saving (using the example of favorites, which is essentially the same as what you need), but with the new Google tools from the commentary above, the logic changes a little, of course - pavlofff