I am working on Recyclerview in which checkboxes are there. I want to know how to use the below to achieve MVVM data binding in android.
#BindingAdapter({"app:setCheckBoxListener"})
public static void setCheckBoxListener(AppCompatCheckBox checkBox, final OnCheckListener onCheckListener) {
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
onCheckListener.onCheckChanged(isChecked, (String) buttonView.getText());
}
});
}
this is the ViewModel class which I am using for the logical part. I want when I check on the checkboxes the data will be saved in the ArrayList.
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;
import com.codestrela.product.adapters.SelectContactAdapter;
import com.codestrela.product.data.Contact;
import com.codestrela.product.fragments.ListDialogFragment;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class ListDialogViewModel {
private static final String TAG = "ListDialogViewModel";
public static final String CONTACT_LIST = "contact_list";
public RowSelectContactViewModel viewModel;
ListDialogFragment listDialogFragment;
ArrayList<RowSelectContactViewModel> selectViewmodel;
ArrayList<Contact> contacts;
public SelectContactAdapter adapter;
public ListDialogViewModel(ListDialogFragment listDialogFragment) {
this.listDialogFragment = listDialogFragment;
adapter = new SelectContactAdapter(new ArrayList<RowSelectContactViewModel>());
selectViewmodel = new ArrayList<>();
onContact();
}
public void onContact() {
contacts = new ArrayList<>();
SharedPreferences sharedPreferences = listDialogFragment.getActivity().getSharedPreferences("shared preference", Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString(CONTACT_LIST, null);
Toast.makeText(listDialogFragment.getActivity(), "" + json, Toast.LENGTH_SHORT).show();
Type type = new TypeToken<ArrayList<Contact>>() {
}.getType();
contacts = gson.fromJson(json, type);
Log.e(TAG, "array size: " + contacts.toString());
for (int i = 0; i < contacts.size(); i++) {
viewModel = new RowSelectContactViewModel();
String name = contacts.get(i).getName();
viewModel.contactName.set(name);
viewModel.contactNumber.set(contacts.get(i).getNumber());
Toast.makeText(listDialogFragment.getActivity(), " check "+viewModel.contactCheckbox.get(), Toast.LENGTH_SHORT).show();
selectViewmodel.add(viewModel);
}
adapter.addAll(selectViewmodel);
}
}
this is the row layout that I am using in the recycler view in the application. This checkbox is there which I am using in the application. Please help me I am very new at this.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="vm"
type="com.codestrela.product.viewmodels.RowSelectContactViewModel" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:checked="#{vm.contactCheckbox.get()}"
android:layout_alignParentLeft="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="8dp"
android:layout_gravity="center">
<TextView
android:id="#+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{vm.contactName}"
android:layout_gravity="center"
android:textSize="18dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{vm.contactNumber}"
android:textSize="14dp"
android:layout_marginTop="4dp"
android:layout_gravity="center"
/>
</LinearLayout></LinearLayout></androidx.cardview.widget.CardView>
</layout>
You don't need to make BindingAdapter ,, it's too easy
according to docs of two-way data binding ,, you will just add this to your xml
it provides setting initial state of checkbox and onCheckedChange
<CheckBox
android:id="#+id/rememberMeCheckBox"
android:checked="#={viewmodel.rememberMe}"
/>
you have to save it to boolean variable
boolean contactCheckbox;
so in your xml it will be
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:checked="#={vm.contactCheckbox}"
android:layout_alignParentLeft="true"/>
just add equal sign = .. it makes the two-way binding works
Related
I use a RecyclerView in an Android app (API 23+) and update its adapter with around 380 items. Even though only 15 items are visible, the RecyclerView's adapter's onBindViewHolder() method gets called for all 380 items. Some threads describe that this happens when the RecyclerView is inside a ScrollView or NestedScrollView; however, that is not the case here. Another suggestion is to set the width of the recycler view to 0dp or to set its height to wrap-content. Neither tip works in this case.
Here is a graphic of the navigation graph:
Here is the code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TABLE TITLE-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/mid_gray"
android:gravity="top"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<TextView
android:id="#+id/txt_table_title_0"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_weight="0.7"
android:text="#string/caja"
android:textStyle="bold" />
<TextView
android:id="#+id/txt_table_title_variedad"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/variedad"
android:textStyle="bold" />
<TextView
android:id="#+id/txt_table_title_date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/ingreso"
android:textStyle="bold" />
<TextView
android:id="#+id/txt_table_title_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:text="#string/semanas"
android:textStyle="bold" />
<TextView
android:id="#+id/txt_table_title_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/cantidad"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Here is the adapter code
package com.plantecuador.poscosecha.adapter;
import android.annotation.SuppressLint;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.plantecuador.poscosecha.R;
import com.plantecuador.poscosecha.db.entities.BoxInside;
import com.plantecuador.poscosecha.event.BoxInsideSelectedEvent;
import com.plantecuador.poscosecha.helper.DateFormatHelper;
import com.plantecuador.poscosecha.viewholder.ThrowOutViewHolder;
import org.greenrobot.eventbus.EventBus;
import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import timber.log.Timber;
public class ThrowOutAdapter extends RecyclerView.Adapter<ThrowOutViewHolder> {
private ArrayList<BoxInside> insides = new ArrayList<>();
#NonNull
#Override
public ThrowOutViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_throw_out, parent, false);
return new ThrowOutViewHolder(view);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(#NonNull ThrowOutViewHolder vh, int position) {
Timber.v("onBindViewHolder called in throwout and position %s", position);
if (position % 2 == 0) {
vh.rowLayout.setBackgroundColor(Color.WHITE);
} else {
vh.rowLayout.setBackgroundColor(Color.parseColor("#D8D8D8"));
}
BoxInside inside = insides.get(position);
vh.txtInsideNumber.setText(inside.getId());
Date date = (inside.getDateCFOrigPacked() == null) ? inside.getDatePacked() : inside.getDateCFOrigPacked();
String strDate = DateFormatHelper.formatToDateString("dd/MM/yy", date);
vh.txtDate.setText(strDate);
vh.txtQuantity.setText(inside.getQuantity() + "");
vh.txtVariety.setText(inside.getVariety() + "");
Instant instantStart = DateTimeUtils.toInstant(date);
LocalDateTime localStart = LocalDateTime.ofInstant(instantStart, ZoneId.systemDefault());
Instant instantEnd = DateTimeUtils.toInstant(new Date());
LocalDateTime localEnd = LocalDateTime.ofInstant(instantEnd, ZoneId.systemDefault());
long weeks = ChronoUnit.WEEKS.between(localStart, localEnd);
vh.txtAge.setText(weeks + "");
assert vh.btnVer != null;
vh.btnVer.setOnClickListener(view -> EventBus.getDefault().post(new BoxInsideSelectedEvent(inside)));
}
#Override
public int getItemCount() {
return insides.size();
}
public void update(List<BoxInside> insides) {
this.insides.clear();
this.insides.addAll(insides);
Timber.v("About to notify dataset changed");
notifyDataSetChanged();
}
}
The behavior is as follows: The adapter's update() method is called with a new list of BoxInside objects when there are updates. I'd like the RecyclerView to obviously clear, update it's dataset, and update the view but not worry about creating ViewHolders outside the visible area until the user scrolls.
Changing from a RelativeLayout to a FrameLayout fixes it. Here is the navigation hierarchy after the fix.
I've created a spinner that takes some user-generated strings (in my case classes - the school type) and displays them in a typical spinner way. My problem occurs when trying to select an item from the spinner. I can tap on the spinner and select the class, but the spinner never shows that I have the class selected. Before adding user-generated strings, I had a string-array xml file that worked perfectly.
I've tried adding notifyDataSetChanged() at the end of the onCreate() method, created a spinner layout with a transparent background and black text, and setting an setOnItemSelectedListener(). None of these worked, so I reverted code back to original state.
Screenshot of problem:
addAssignment.java
package com.nbdeg.unityplanner;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Spinner;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.nbdeg.unityplanner.data.Assignments;
import com.nbdeg.unityplanner.data.Classes;
import java.util.ArrayList;
public class addAssignment extends AppCompatActivity {
EditText mAssignmentName;
EditText mDueDate;
EditText mExtraInfo;
Spinner mDueClass;
SeekBar mPercentComplete;
int percentComplete = 0;
FirebaseAnalytics mFirebaseAnalytics;
DatabaseReference assignmentDb;
DatabaseReference classDb;
FirebaseUser user;
long assignmentCounter;
ArrayList<String> classList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_assignment);
// Sets title to "Create an assignment"
try {getSupportActionBar().setTitle("Create An Assignment");}
catch (NullPointerException e) {
e.printStackTrace();
}
// Getting number of assignments (serves as assignment ID in database)
Bundle extras = getIntent().getExtras();
assignmentCounter = extras.getLong("counter");
// Finds firebase database
user = FirebaseAuth.getInstance().getCurrentUser();
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
assignmentDb = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).child("assignments");
classDb = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).child("classes");
// Gets all classes
classDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
Classes mClass = userSnapshot.getValue(Classes.class);
Log.i("Info", "Class loaded: " + mClass.getClassName());
classList.add(mClass.getClassName());
}
Log.i("Info", "Classes loaded: " + classList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("DB", "Error: " + databaseError.getMessage());
}
});
// Find view by ID calls
mAssignmentName = (EditText) findViewById(R.id.assignment_name);
mDueDate = (EditText) findViewById(R.id.due_date_edittext);
mExtraInfo = (EditText) findViewById(R.id.extra_homework_info);
mDueClass = (Spinner) findViewById(R.id.class_spinner);
mPercentComplete = (SeekBar) findViewById(R.id.percentComplete);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.spinner_layout, classList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mDueClass.setAdapter(adapter);
// Sets DueDate EditText to open a datepicker when clicked
new EditTextDatePicker(this, R.id.due_date_edittext);
mPercentComplete.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
percentComplete = progress;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
// Adds a SAVE button to the Action Bar
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.save, menu);
return true;
}
// Gets and saves information when SAVE is clicked
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Getting information from views
String dueDate = mDueDate.getText().toString();
String assignmentName = mAssignmentName.getText().toString();
String extraInfo = mExtraInfo.getText().toString();
String dueClass = mDueClass.getItemAtPosition(mDueClass.getSelectedItemPosition()).toString();
mFirebaseAnalytics.logEvent("Assignment Created", null);
Log.i("DB", "Creating assignment named " + assignmentName);
assignmentDb.child(Long.toString(assignmentCounter)).setValue
(new Assignments(assignmentName, dueClass, dueDate, extraInfo, percentComplete));
/*
// Test to make sure info is being collected correctly.
Log.i("Class", dueClass);
Log.i("Due", dueDate);
Log.i("Name", homeworkName);
Log.i("Extra", extraInfo);
*/
// Bring user back to MainActivity
startActivity(new Intent(addAssignment.this, MainActivity.class));
return super.onOptionsItemSelected(item);
}
}
activity_add_assignment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_add_homework"
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"
tools:context="com.nbdeg.unityplanner.addAssignment">
<EditText
android:layout_width="match_parent"
android:layout_height="40dp"
android:inputType="textCapSentences"
android:ems="10"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/assignment_name"
android:hint="Assignment Name"
android:padding="5dp"
android:textSize="18sp"
android:background="#null" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#c0c0c0"
android:layout_below="#id/assignment_name"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="43dp"
android:orientation="horizontal"
android:layout_below="#id/assignment_name"
android:layout_alignParentStart="true"
android:id="#+id/linearLayout">
<Spinner
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/class_spinner"
android:theme="#android:style/Theme.Holo.Light.DarkActionBar"
android:layout_weight="1"
android:background="#null"/>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#c0c0c0"/>
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/due_date_edittext"
android:padding="5dp"
android:focusable="false"
android:hint="Due Date"
android:textSize="16sp"
android:background="#null" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#c0c0c0"
android:layout_below="#id/linearLayout"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_below="#+id/linearLayout"
android:layout_alignParentStart="true"
android:id="#+id/percentCompleteLayout"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Completion"
android:padding="5dp"
android:textColor="#color/black"
android:textSize="15sp"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/percentComplete"
android:layout_marginBottom="1dp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#c0c0c0"
android:layout_below="#id/percentCompleteLayout"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:ems="10"
android:id="#+id/extra_homework_info"
android:hint="Extra Infomation"
android:textSize="16sp"
android:layout_below="#id/percentCompleteLayout"
android:layout_alignParentStart="true"
android:layout_marginTop="2dp"
android:padding="5dp"
android:background="#null" />
</RelativeLayout>
spinner_layout.xml*
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:gravity="left"
android:padding="5dip"
android:textColor="#android:color/black"
android:background="#android:color/transparent"
/>
I'm wondering if there is a way to fix this and have the spinner display the default / user choice. If you need any more of the code, all of it can be found in the GitHub. Thanks in advance for all answers!
Solution: Try loading the classes prior to starting the activity, for example in the MainActivity. Then pass the values along through an intent.
Example:
MainActivty.java
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Launch Add Homework Activity
Intent intent = new Intent(MainActivity.this, addAssignment.class);
intent.putExtra("classListNames", classListNames);
startActivity(intent);
...
classDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
classList.clear();
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
Classes mClass = userSnapshot.getValue(Classes.class);
Log.i(TAG, "Class loaded: " + mClass.getClassName());
classList.add(mClass);
classListNames.add(mClass.getClassName());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "Error: " + databaseError.getMessage());
}
});
addAssignment.java
// Gets class list
Bundle extras = getIntent().getExtras();
classListNames = extras.getStringArrayList("classListNames");
...
mDueClass = (Spinner) findViewById(R.id.class_spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.spinner_layout, classListNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mDueClass.setAdapter(adapter);
Cause: After some debugging, I discovered the cause of the problem to be timing differences. The app would request the classes be sent, create the spinner, then load the classes. The difference in timing was milliseconds, but just enough to cause the problem.
Actually, I was trying to implement a shopping cart using Android Studio. There is a custom list view in the main page included an "Add to Cart" button. So, whenever I click on the button the item must be added in the cart. But, I have no idea. Please guys, help me out. I'm a newbie.
Here is the Product Adapter
package com.example.raswap.octomatic;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by aurora on 22/03/16.
*/
public class Pro_Adapter extends ArrayAdapter {
List list = new ArrayList();
public Pro_Adapter(Context context, int resource) {
super(context, resource);
}
static class DataHandler{
ImageView img;
TextView p_name;
TextView b_name;
TextView price;
Button b_atc;
}
#Override
public void add(Object object) {
list.add(object);
}
#Override
public int getCount() {
return this.list.size();
}
#Override
public Object getItem(int position) {
return this.list.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
DataHandler handler;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.e_layout, parent, false);
handler = new DataHandler();
handler.img = (ImageView)row.findViewById(R.id.pro_image);
handler.p_name = (TextView)row.findViewById(R.id.pro_name);
handler.b_name = (TextView)row.findViewById(R.id.brand);
handler.price = (TextView)row.findViewById(R.id.pricing);
handler.b_atc = (Button)row.findViewById(R.id.atc);
row.setTag(handler);
}else{
handler = (DataHandler)row.getTag();
}
Product_data_provider dataProvider;
dataProvider = (Product_data_provider)this.getItem(position);
handler.img.setImageResource(dataProvider.getPro_img_resource());
handler.p_name.setText(dataProvider.getPro_name());
handler.b_name.setText(dataProvider.getBr_name());
handler.price.setText(dataProvider.getPricing());
return row;
}
}
Here is the Main Activity class:
package com.example.raswap.octomatic;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
public class E_shop extends Activity {
ListView listView;
int[] emage = {R.drawable.gb32, R.drawable.tb1, R.drawable.dvd};
String[] pro_name;
String[] br_name;
String[] price;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.activity_e_shop);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_titlebar);
View z = findViewById(R.id.oct_logo);
z.setClickable(true);
z.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(E_shop.this, MainActivity.class));
}
});
View x = findViewById(R.id.for_user_info);
x.setClickable(true);
x.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(E_shop.this, UserInformation.class));
}
});
Pro_Adapter adapter = new Pro_Adapter(getApplicationContext(),R.layout.e_layout);
ListView listView = (ListView)findViewById(R.id.e_list);
listView.setAdapter(adapter);
pro_name = getResources().getStringArray(R.array.nameOfProduct);
br_name = getResources().getStringArray(R.array.branding);
price = getResources().getStringArray(R.array.pricing);
int i = 0;
for(String pro: pro_name){
Product_data_provider dataProvider = new Product_data_provider(emage[i],pro, br_name[i], price[i]);
adapter.add(dataProvider);
i++;
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch(position){
case 0:
Intent newActivity = new Intent(E_shop.this, Product_Desc.class);
newActivity.putExtra("pro_emage",R.drawable.gb32);
newActivity.putExtra("title","Kingston 32Gigs Pen Drive");
newActivity.putExtra("desc", "Store a huge collection of data in a generous 32GB space of this Kingston pen drive and carry it along. It has a sleek design with a smooth finish, and a pretty-looking charm bearing the Kingston logo dangles from this pen drive. Featured in a size of 3 x 1.2 x 0.5 cm, this Kingston 32GB pen drive weighs only 5g. You can easily tuck it away in the pocket of your laptop bag, purse or your shirt pocket with its compact and light weight.");
startActivity(newActivity);
break;
case 1:
Intent Activity1 = new Intent(E_shop.this, Product_Desc.class);
Activity1.putExtra("pro_emage",R.drawable.tb1);
Activity1.putExtra("title","Samsung 1TB Portable Hard Disk");
Activity1.putExtra("desc", "From college to school students, all deal with transferring files, software and applications from various systems that are large in size. With the advancements in media technology on the rise, we require a large amount of space to store our data. Even most of the growing companies require a secure means of storing data for analyses. All of this embarks on the need for a reliable hard disk. The top quality brand of Samsung brings you this sleek and portable hard drive ideally designed for continuous usage. Now you can store 2TB of diverse data easily. This, sleek hard disk comes with 36 months warranty. The body of this drive has a smart construction. The Samsung external hard disk comes in a sturdy design.");
startActivity(Activity1);
break;
case 2:
Intent Activity2 = new Intent(E_shop.this, Product_Desc.class);
Activity2.putExtra("pro_emage", R.drawable.dvd);
Activity2.putExtra("title", "A pack of 50 DVD's");
Activity2.putExtra("desc", "Create and store digital video, audio and multimedia files, Stores up to 4.7GB or more than 2 hours of MPEG2 video, Has 7 times the storage capacity of a CDR, Sony branded 16X DVD-R in a 100 pack Spindle, AccuCORE Technology");
startActivity(Activity2);
break;
}
}
#SuppressWarnings("unused")
public void onClick(View v){
}
});
}
}
Here is the Product Data Provider Class:
package com.example.raswap.octomatic;
/**
* Created by aurora on 22/03/16.
*/
public class Product_data_provider {
private int pro_img_resource;
private String pro_name;
private String br_name;
private String pricing;
public int getPro_img_resource() {
return pro_img_resource;
}
public Product_data_provider(int pro_img_resource, String pro_name, String br_name, String pricing){
this.setPro_img_resource(pro_img_resource);
this.setPro_name(pro_name);
this.setBr_name(br_name);
this.setPricing(pricing);
}
public void setPro_img_resource(int pro_img_resource) {
this.pro_img_resource = pro_img_resource;
}
public String getPro_name() {
return pro_name;
}
public void setPro_name(String pro_name) {
this.pro_name = pro_name;
}
public String getBr_name() {
return br_name;
}
public void setBr_name(String br_name) {
this.br_name = br_name;
}
public String getPricing() {
return pricing;
}
public void setPricing(String pricing) {
this.pricing = pricing;
}
}
Now, Custom ListView XML file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/oneL"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="horizontal">
<ImageView
android:id="#+id/pro_image"
android:src="#drawable/gb32"
android:layout_width="160dp"
android:layout_height="match_parent" />
<LinearLayout
android:background="#afeeee"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Product Name"
android:id="#+id/pro_name"
android:textColor="#000"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Branding"
android:id="#+id/brand"
android:textColor="#000"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Price"
android:textColor="#000"
android:id="#+id/pricing"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add to Cart"
android:id="#+id/atc" />
</LinearLayout>
</LinearLayout>
<View
android:layout_below="#+id/oneL"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#000"/>
</RelativeLayout>
</RelativeLayout>
and finally the main layout XML file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="com.example.raswap.octomatic.E_shop">
<ListView
android:id="#+id/e_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
Add your button's OnClick event in the Pro_Adapter's getView() methond as you do normally in your activities' onCreate() method.
Implement OnClickListener in your adapter class and get the Button click first and do the other task when you get the event. If you need the call back to your main activity class implement your own listener.follow the link enter link description here
Add the onClickListener to your Button in getView() of your ListAdapter.
If you want handle event click button in row, i'm think you should answer set button onclick event for every row of listview
you can try this.
Change in custom Listview xml file.
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add to Cart"
android:onClick="AddCart"
android:id="#+id/atc" />
In MainActivity
public void AddCart(View v)
{
LinearLayout vwParentRow = (LinearLayout)v.getParent();
TextView child = (TextView)vwParentRow.getChildAt(0);
child.setText("I've been clicked!");
vwParentRow.refreshDrawableState();
}
I have a simple table layout that I want to populate just by initialising a specific type
of object in my onCreate method. First off this is the layout I have
jobs_table.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout android:id="#+id/Jobs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="*"
xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow android:id="#+id/JobRow" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:id="#+id/JobID" android:layout_column="1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/JobStatus" android:layout_column="2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/Customer" android:layout_column="3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/Department" android:layout_column="4" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/DocType" android:layout_column="5" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
</TableRow>
</TableLayout>
And the activity
package com.producermobile;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import com.producermobile.jobs.ProducerJobRows;
public class JobRowsActivity extends Activity {
private BatchingJobRows jobRows;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jobs_table);
jobRows = new BatchingJobRows(this);
}
}
Now the idea will be when I create my jobRows the data for the table will be loaded by the BatchingJobRows object, which should hopefully then be available to my activity. I don't have a way of checking this at the mo though so I'm not sure if the concept is right (my main worry is the while loop which is adding rows to the table).
Anyway here's a simplified version of what's happening in the BatchingJobRows.
package com.producermobile.jobs;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.producermobile.R;
public class BatchingJobRows {
private TableLayout table;
private View tableView;
private Context context;
private HashMap<String,ArrayList<String>> jobs;
private ArrayList<String> jobsVals;
public BatchingJobRows(Context context) {
this.context = context;
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
tableView = inflater.inflate(R.layout.jobs_table, null);
table = (TableLayout) tableView.findViewById(R.id.Jobs);
jobVals = new ArrayList<String>();
jobVals.add("HELD");
jobVals.add("DELL");
jobVals.add("PRINT");
jobVals.add("STATEMENT");
jobs = new HashMap<String,ArrayList<String>>();
jobs.put("012345",jobVals);
jobs.put("123456",jobVals);
this.setRows();
}
public void setRows() {
Iterator<String> keys = jobs.keySet().iterator();
while(keys.hasNext()) {
//Init Objects
TableRow row = (TableRow) TableView.findViewById(R.id.JobRow);
TextView jobid = (TextView) tableView.findViewById(R.id.JobID);
TextView jobstatus = (TextView) tableView.findViewById(R.id.JobStatus);
TextView customer = (TextView) tableView.findViewById(R.id.Customer);
TextView department = (TextView) tableView.findViewById(R.id.Department);
TextView doctype = (TextView) tableView.findViewById(R.id.DocType);
String key = keys.next();
jobid.setText(key);
jobstatus.setText(jobs.get(key).get(0));
customer.setText(jobs.get(key).get(1));
department.setText(jobs.get(key).get(2));
doctype.setText(jobs.get(key).get(3));
row.addView(jobid);
row.addView(jobstatus);
row.addView(customer);
row.addView(department);
row.addView(doctype);
table.addView(row);
}
}
}
Well this is not a direct answer to your question but what I think you should do is create a list activity, and move this functionality down into a ListAdapter of some type. We can help you with question on how to set that up. Its probably easier than the route you are going, and more familiar to people on this board. So i would recommend taking the conventional approach on this. Use ListActivity, and ListAdapter Base or Cursor depending on your needs.
I am trying to create a simple program which displays a "shopping
cart" list of items, along with a few buttons below it to manage the
cart.
The biggest problem is that items are getting duplicate entries in the
list view. That is, for every item I want to enter I see it appear
two times in the list view. What's the problem? Also, the scrollable
area of my cart is not big enough. How do I set it so that it is
bigger but I can still see my buttons? Perhaps I should put the
buttons above the cart?
Here is my shopping cart's layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shopping Cart" />
<ScrollView android:id="#+id/ScrollView01"
android:layout_width="fill_parent"
android:layout_height="110px">
<ListView
android:id="#+id/BookList"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
</ScrollView>
<Button android:text="Add Another Book"
android:id="#+id/AddAnother"
android:layout_width="250px"
android:textSize="18px"
android:layout_height="55px">
</Button>
<Button android:text="Checkout"
android:id="#+id/Checkout"
android:layout_width="250px"
android:textSize="18px"
android:layout_height="55px">
</Button>
</LinearLayout>
Here is the layout for individual row items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="8dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/BookTitle"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:gravity="center_vertical"
/>
<TextView
android:id="#+id/BookPrice"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
/>
</LinearLayout>
<Button
android:id="#+id/buttonLine"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:text="Delete"
/>
</LinearLayout>
here is the java code for the shopping cart activity:
package com.sellbackyourbook.sellback;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import android.app.Activity;
//import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
public class cart extends Activity
{
private ListView m_bookListView;
private BookAdapter m_adapter;
//private static String[] data = new String[] = { ""
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
ShoppingCartSingleton shoppingCart = ShoppingCartSingleton.getInstance();
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppingcart);
this.m_adapter = new BookAdapter(this, R.layout.cartitem,
shoppingCart.m_books);
m_bookListView = (ListView) findViewById(R.id.BookList);
m_bookListView.setAdapter(this.m_adapter);
//setListAdapter(this.m_adapter);
if (shoppingCart.m_books != null && shoppingCart.m_books.size() > 0)
{
//m_adapter.notifyDataSetChanged();
try
{
//m_adapter.clear();
//for(int i=0;i<1;i++)
Log.i("ARRAY", "m_books.size() before loop" + shoppingCart.m_books.size());
int size = shoppingCart.m_books.size();
for(int i=0;i<size;i++)
{
Log.i("ARRAY", "size in loop" + size);
Log.i("ARRAY", "adding item to adapter" + i);
m_adapter.add(shoppingCart.m_books.get(i));
}
} catch (RuntimeException e) {
e.printStackTrace();
}
//m_adapter.notifyDataSetChanged();
}
Button buttonAddAnother = (Button) findViewById(R.id.AddAnother);
buttonAddAnother.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
}
});
// TODO: only show this button if the shopping cart is not empty
Button buttonCheckout = (Button) findViewById(R.id.Checkout);
buttonCheckout.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
// TODO: open sellbackyourbook website using book ISBNs
ShoppingCartSingleton shoppingCart = ShoppingCartSingleton.getInstance();
String isbnList = "";
String checkoutURL = "http://www.sellbackyourbook.com/androidcart.php?isbn=";
for (Iterator<Book> i = shoppingCart.m_books.iterator(); i.hasNext(); )
{
Book currentBook = (Book) i.next();
isbnList = isbnList + currentBook.getBookISBN() + ",";
}
checkoutURL = checkoutURL + isbnList;
Log.i("CHECKOUT URL", "checkout URL to submit: " + checkoutURL);
Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.parse(checkoutURL));
startActivity(myIntent);
}
});
}
private class BookAdapter extends ArrayAdapter<Book> {
private ArrayList<Book> books;
public BookAdapter(Context _context, int _textViewResourceId, ArrayList<Book> _books)
{
super(_context, _textViewResourceId, _books);
this.books = _books;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
System.out.println("getView " + position + " " + convertView);
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.cartitem, null);
}
Book b = books.get(position);
if (b != null)
{
TextView bTitle = (TextView) v.findViewById(R.id.BookTitle);
TextView bPrice = (TextView) v.findViewById(R.id.BookPrice);
if (bTitle != null)
{
bTitle.setText(b.getBookTitle());
}
if (bPrice != null)
{
bPrice.setText(b.getBookPrice());
}
}
return v;
}
}
}
Here is the Java code for my shopping cart. Am I using the singleton correctly? I really just wanted a quick and dirty way to allow multiple activities access to the shopping cart, as a different activity actually grabs the books from the user and this activity displays them in the cart.
I had an issue iterating through the books in onCreate() as well. the size() function kept increasing in the loop for some reason, so I changed the code and added a "size" variable to avoid making the size() call in the loop itself. I'm not really sure what that was all about.
I'm doing exactly the same thing and my getView is not called at all.
here is the script I was inspired by maybe it would help :
http://mfarhan133.wordpress.com/2010/10/14/list-view-tutorial-for-android/
Yes you are right at the point of BookAdapter's constructor. But the getView() method of BookAdapter is wrong. Please have a look at http://www.youtube.com/watch?v=wDBM6wVEO70 (from Google) to get the right way on how to work with ListView.
Removing the loop where I had this fixed the problem:
m_adapter.add(shoppingCart.m_books.get(i));
It seems like the BookAdapter constructor already took care of populating it, so I was duplicating the items by using the add() method.