I'm trying to implement an Android app for sudoku game, and i created a customized adapter for that. i want make edit text for cells the user is allowed to modify, and textview for cell filled by the program, the number of ediTexts and textViews will be random. how do specify that in the adapter ?
This is my adapter :
public class SodukuAdapter extends BaseAdapter {
ArrayList<String> items;
static Activity mActivity;
private static LayoutInflater inflater = null;
public SodukuAdapter (Activity activity, ArrayList<String> tempTitle,) {
mActivity = activity;
items = tempTitle;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public final int getCount() {
return items.size();
}
#Override
public final Object getItem(int position) {
return items.get(position);
}
#Override
public final long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = null;
v = inflater.inflate(R.layout.item, null);
EditText et = (EditText) v.findViewById(R.id.et);
et.setText(items.get(position));
return v;
}
}
You can place both views in the same parent (e. g. parent is a RelativeLayout or a FrameLayout) so they are on top of each other. Than you simply hide one of them and show the other using setVisibility() in your getView() method of the adapter.
Of course you would need a datasource object which keeps track of whether a view should show the TextView or the EditText:
class SodokuItem {
public boolean isStatic;
public String text;
}
...
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.item, null);
SodokuItem item = items.get(position);
EditText et = (EditText) v.findViewById(R.id.et);
TextView tv = (TextView) v.findViewById(R.id.tv);
if(item.isStatic){
et.setVisibility(GONE);
tv.setText(item.text);
}else{
tv.setVisibility(GONE);
et.setText(item.text);
}
return v;
}
Related
Am building an app for exploring files and am using the android native resource layout for data population called android.R.simple_list_item_1, i have tried going through the methods of a listview to see if i can add a drawable to the left of each item in my list but didn't manage. So the only way i get to access a view from a listview is on event OnItemClick where the view tapped is passed as parameter to the method and then i can format it this way for the drawable
public class MainActivity extends AppCompatActivity {
//Define a listview for holding the data mined from storage
public ListView mydata;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Define the listview
mydata=findViewById(R.id.data);
mydata.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
//Cast view to TextView at position
TextView r=(TextView)view;
//get the drawable and set to textview
Drawable mydraw= ResourcesCompat.getDrawable(getResources(),R.drawable.ic_baseline_file_copy_24,null);
r.setCompoundDrawables(mydraw,null,null,null);
}
}
}
Is there in which i can get all the views in the listview, create a loop, iterate through all of them and cast to TextView array and then set my drawable to the TextView(s)?
final static class YourItemClass {
...
}
final static class ViewHolder {
TextView mTextView;
private ViewHolder(#NonNull final View simpleListItem1) {
if (!(simpleListItem1 instanceof TextView)) throw new IllegalArgumentException("TextView was expected as root of Layout");
this.mTextView = (TextView)simpleListItem1;
}
}
final class CustomArrayAdapter extends ArrayAdapter<YourItemClass> {
private final Drawable mDrawable;
private final LayoutInflater mLayoutInflater;
public CustomArrayAdapter(#NonNull final Context context, #NonNull final List<YourItemClass> objects) {
super(context, resource, objects);
this.mDrawable = ResourcesCompat.getDrawable(getResources(),R.drawable.ic_baseline_file_copy_24,null);
this.mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull final ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = this.mLayoutInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
final YourItemClass cYourItemClassAtSpecificPosition = this.getItem(position);
holder.mTextView.setCompoundDrawables(this.mDrawable, null, null, null);
return convertView;
}
}
Then from your Activity/Fragment:
private void setItemsToListView(#NonNull final List<YourItemClass> items) {
mListView.setAdapter(new CustomArrayAdapter(getActivity(), items));
}
This code will run "setCompoundDrawables()" for each row displayed in the ListView.
I am trying to get the total of numbers in an sql table,
i first connected between android and sql but i can't
sum the numbers in the table column and show them
in a textview,like i want to get the total
of numbers in a column then
display them in a text view
,can someone help me with this task?
here is the code i used for
the listview
public class MyAppAdapter extends BaseAdapter //has a class viewholder which holds
{
public class ViewHolder
{
TextView textDate;
TextView textTotal;
TextView textLastTotal;
TextView textCount;
TextView textTaxs;
}
public List<ClassListItems2> parkingList;
public Context context;
ArrayList<ClassListItems2> arraylist;
private MyAppAdapter(List<ClassListItems2> apps, Context context)
{
this.parkingList = apps;
this.context = context;
arraylist = new ArrayList<ClassListItems2>();
arraylist.addAll(parkingList);
}
#Override
public int getCount() {
return parkingList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) // inflating the layout and initializing widgets
{
View rowView = convertView;
ViewHolder viewHolder= null;
if (rowView == null)
{
LayoutInflater inflater = getLayoutInflater();
rowView = inflater.inflate(R.layout.listcontent2, parent, false);
viewHolder = new ViewHolder();
viewHolder.textDate = (TextView) rowView.findViewById(R.id.date);
viewHolder.textLastTotal = (TextView) rowView.findViewById(R.id.lasttotal);
viewHolder.textTaxs = (TextView) rowView.findViewById(R.id.date3);
viewHolder.textCount = (TextView) rowView.findViewById(R.id.InvoicescCount);
viewHolder.textTotal = (TextView) rowView.findViewById(R.id.total);
rowView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
// here setting up names and images
viewHolder.textDate.setText(parkingList.get(position).getDate()+"");
viewHolder.textTotal.setText(parkingList.get(position).getTotal());
viewHolder.textLastTotal.setText(parkingList.get(position).getLasttotal());
viewHolder.textTaxs.setText(parkingList.get(position).getTaxs());
viewHolder.textCount.setText(parkingList.get(position).getInvoicecount());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//What happens when you click on a place!
}
});
return rowView;
}
This Adapter is feed with a Collection (List) in his constructor.
To know total numbers, in Activity/Fragment that handle that Collection use:
parkingList.size()
To get sum:
float total;
for (ClassListItems2 actualItem : parkingList) {
total += actualItem.getTotal()
}
All of this logic must be executed in Activity/Fragment, never in Adapter because the Adapter only got presentation/visual logic.
I have a ListView and a CustomAdapter. The elements are all successfully loaded into the list. Now I want to change the background color of a certain element of the list by clicking on an external button. But I do not know how to access a specific item in the list.
Here is the CustomAdapter class:
public class CustomAdapter extends BaseAdapter {
private Context ctx;
private int resource;
private List<ItemModel> items;
public PreorderListAdapter(Context context, int resource, List<ItemModel> items){
this.ctx = context;
this.resource = resource;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public ItemModel getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#NonNull
#Override
public View getView(int i, View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if(view == null){
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(resource, null);
}
TextView text1 = (TextView) view.findViewById(R.id.text1);
TextView text2 = (TextView) view.findViewById(R.id.text2);
TextView text3 = (TextView) view.findViewById(R.id.text3);
ItemModel item = items.get(i);
text1.setText(item.getName());
text2.setText(item.getOption2());
text3.setText(item.getOption3());
return view;
}
}
You can do it like this inside your getView() method
view.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
view.setBackgroundColor(ContextCompat.getColor(this, R.color.yourcolor));
}
});
If you have a button on your view then performs the listener on that button
If you want to get your selected item view from your parent activity then :
yourlistview.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent,View view, int position, long id)
{
selectedposition = position ;
}
});
View view = listView.getAdapter().getView(selectedposition,null,listview);
Then change its background:
view.setBackgroundColor(ContextCompat.getColor(this, R.color.yourcolor));
please define your color in your color.xml file
If you have more than one view then , create an ArrayList<View> and do some loop
create a custom listener interface in your activity and your
adapter will implement this.
public interface OnClickListenerFromActivity {
void onActivityButtonClick(int position);
}
on click in your button call your listener's method
mOnClickListenerFromActivity.onActivityButtonClick(mList.getItem(yourPostion));
implement this listener into your adapter
public class CustomAdapter extends BaseAdapter implements Activity.OnClickListenerFromActivity {
private Context ctx;
private int resource;
private List<ItemModel> items;
public PreorderListAdapter(Context context, int resource, List<ItemModel> items){
this.ctx = context;
this.resource = resource;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public ItemModel getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#NonNull
#Override
public View getView(int i, View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if(view == null){
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(resource, null);
}
TextView text1 = (TextView) view.findViewById(R.id.text1);
TextView text2 = (TextView) view.findViewById(R.id.text2);
TextView text3 = (TextView) view.findViewById(R.id.text3);
ItemModel item = items.get(i);
text1.setText(item.getName());
text2.setText(item.getOption2());
text3.setText(item.getOption3());
return view;
}
public void onActivityButtonClick(int position) {
// get your item through position and
// set your color here
}
}
I used fragment in my app and i'm using SQLite to save local data. But when I finished saving data, and I swipe the page, my listView is not refreshed with new data (Only showing old data). I have tried to provide a method notifyDataSetChanged() on my adapter, but it's not working.
My Base Adapter class :
public class LocalDataAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<LocalDataBean> data;
private static LayoutInflater inflater = null;
public LocalDataAdapter(Activity a, ArrayList<LocalDataBean> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setItem(ArrayList<LocalDataBean> data){
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView nama_konsumen = (TextView) v.findViewById(R.id.nama_konsumen);
TextView no_telp = (TextView) v.findViewById(R.id.no_telp);
TextView no_hp_cdma = (TextView) v.findViewById(R.id.no_hp_cdma);
TextView no_hp_gsm = (TextView) v.findViewById(R.id.no_hp_gsm);
LocalDataBean obj = (LocalDataBean) getItem(position);
nama_konsumen.setText(obj.getNamaKonsumen());
no_telp.setText(obj.getNoTelp());
no_hp_cdma.setText(obj.getNoCMDA());
no_hp_gsm.setText(obj.getNoGSM());
return v;
}
}
My fragment class :
public class LocalDataFragment extends Fragment {
View view;
Activity act;
SQLHandlerBean utilSql;
ArrayList<LocalDataBean> localdatabean = new ArrayList<LocalDataBean>();
LocalDataAdapter adapter;
ListView list;
public static final String TAG = LocalDataFragment.class.getSimpleName();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_local_data, null);
act = getActivity();
list = (ListView) view.findViewById(R.id.listViewLocalData);
utilSql = new SQLHandlerBean(this.act);
adapter = new LocalDataAdapter(act, localdatabean);
localdatabean = new ArrayList<LocalDataBean>();
list.setAdapter(adapter);
if (utilSql.ReadAllLocalData().size() < 1) {
Toast.makeText(act, "DATA EMPTY!", Toast.LENGTH_LONG).show();
} else {
localdatabean = utilSql.ReadAllLocalData();
Log.e(TAG, "TOTAL DATA : "+localdatabean.size());
adapter.setItem(localdatabean);
adapter.notifyDataSetChanged();
}
return view;
}
}
Is adapter.notifyDataSetChanged() placement correct?
No, the placement is not in the right place.
As you have placed the notifyDataSetChanged() inside of the onCreateView() method. It will be only invoked 1st time the fragment is launched.
Rather you can add a refresh button in your layout (or in you action bar). And along with the insertion/deletion method of the data, place the notifyDataSetChanged() at the bottom of the click event of that button.
By doing this user can refresh the page whenever they want.
And if you want to refresh the page by swipping the view then, SwipeRefreshLaoyout could be a perfect alternative.
You can check this blog.
The current project I have includes a ListView with a Custom Adapter. However, I am now interested in adding multiple types of views to my ListView but after several attempts I have been unable to add the two sources of code together to successfully integrate them.
Article on ListView with multiple views: ListView Article for multiple views
The custom adapter in my current code retrieves the data from another class called getData which is referenced by "data".
Code from article (ListView with multiple views):
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
private TreeSet mSeparatorsSet = new TreeSet();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
Current code (ListView with custom adapter):
FragmentA.java
package com.example.newsapp;
public class FragmentA extends Fragment{
getData data = getData.getMyData();
public Integer ArticleID;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment_a, container, false);
ListView listView = (ListView)V.findViewById(R.id.list)
CustomList adapter = new
CustomList(getActivity(), data.Headline.toArray(new String[data.Headline.size()]), data.Description.toArray(new String[data.Description.size()]), data.BitmapList.toArray(new Bitmap[data.BitmapList.size()]), data.ArticleID.toArray(new Integer[data.ArticleID.size()]));
listView.setAdapter(adapter);
listView.setOnItemClickListener(this); //Removed on click item event code.
return V;
}
CustomList.java
package com.example.newsapp;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
return rowView;
}
}
Edit:
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
int viewType = getItemViewType(position);
View rowView = null;
switch(viewType) {
case 0:
LayoutInflater inflater = context.getLayoutInflater();
rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
case 1:
LayoutInflater inflater2 = context.getLayoutInflater();
rowView= inflater2.inflate(R.layout.single_row_loadmore, null, true);
}
return rowView;
}
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
}
First, a bit of an aside: you should create a class that encapsulates a headline, description, etc. and use an array/collection of those objects to back your adapter. It will be far easier than managing many disparate arrays of things, especially if one day you decide you need another attribute of an Article (its category, for example).
class Article {
int id;
String headline;
String description;
Bitmap picture;
}
With regard to your ListView, the magic happens in the methods getItemViewType() and getViewTypeCount(). In getViewTypeCount() you return the maximum number of row types -- the article you posted uses two row types and so returns 2. In getItemViewType() you return a value between zero and (viewTypeCount - 1) -- in the article, his implementation can return 0 or 1 because his viewTypeCount is 2.
How you decide which row type applies to each item is entirely up to you. If, for example, you wanted to simply alternate view types on every row, you can do this:
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
In other applications you would probably inspect the item at the given position to help you determine what should be returned in getItemViewtype().
The reason this functionality exists is that getView() provides a parameter (called convertView) that is a row which has been recycled. In order to give you an appropriate convertView, ListView needs to first know what row type it was. When you want to implement getView() for an adapter with multiple row types, it generally looks something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
switch(viewType) {
case 0:
return setUpOneViewType(position, convertView, parent);
case 1:
return setUpAnotherViewType(position, convertView, parent);
}
}
Note the cases for the switch statement correspond to the possible values that can be returned from getItemViewType(). These could be static final members.
I highly suggest watching The World of ListView. That video covers this topic as well as how to properly use convertView in your adapter implementation.