I'm reading in places that it's necessary to have a main method in each class like this:
public static void main(String args [ ]) { }
However, none of my classes in my current project contain such a method, and so far my app experiences no issues...here's one of my classes for reference.
public class GridAdapter extends BaseAdapter {
private final String[] classes = {"Database"}; // Sets the labels for each button
private Context mContext;
public GridAdapter(Context c) {
mContext = c;
}
public int getCount() { //autogenerated tab, returns length of an array.
return mThumbIds.length;
}
// The position an item is in in an array.
public Object getItem(int position) {
return mThumbIds[position];
}
// Gets the ID of each item in the array.
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) { // if it's not recycled, initialize some attributes
gridView = new View(mContext);
gridView = inflater.inflate(R.layout.gridset, null);
TextView textView = (TextView) gridView
.findViewById(R.id.label);
textView.setText(classes[position]);
ImageView imageView = (ImageView) gridView
.findViewById(R.id.img);
imageView.setImageResource(mThumbIds[position]);
} else {
gridView = convertView;
}
return gridView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.img};
}
Is it because I'm extending something (in this case BaseAdapter)? Right now the classes that are currently complete and actually function have an extension, So I am wondering if my WIP classes that don't will need a main() method.
Your reference reads "in at least one class" and pertains to a standalone Java SE program.
In Android you, however, do not need main at all. Your Activities will be brought to life by Android OS calling callbacks into your Activities such as onCreate, onPause etc...
Related
i think that this can be done, but maybe im wrong (Im sure im wrong). I have this adapter that sometimes uses a List of Class1 and in other moments uses a list of Class2. So, can i do TWO differents constructors where un the first one i use List1 and in the other one i use the List2?
public class SpinnerAdapter extends BaseAdapter {
private List<String> listaDeTexto;
private Activity activity;
private LayoutInflater layoutInflater;
private List<MetodoDePago> listaMetodosDePago;
private List<Banco> listaDeBancos;
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<MetodoDePago> listaMetodosDePago) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaMetodosDePago = listaMetodosDePago;
}
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<Banco> listaDeBancos) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaDeBancos = listaDeBancos;
}
#Override
public int getCount() {
return listaDeTexto.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view = layoutInflater.inflate(R.layout.spinner_custom,null);
}
TextView textView = view.findViewById(R.id.textViewSpinner);
textView.setText(listaDeTexto.get(position));
ImageView imageView = view.findViewById(R.id.imgViewSpinner);
Glide.with(view)
.load(listaMetodosDePago.get(position).getThumbnail())
.into(imageView);
return view;
}
}
Due to type erasure in Java, you are basically declaring two constructors which look like, SpinnerAdapter(List l1, Activity a, List l2) { } to Java.
A simple solution would be to create one constructor and add a type argument. So, something like, SpinnerAdapter(List l1, Activity a, List l2, int type) { }.
You can then check the type value in the constructor and the getView(...) method to initialize your variables as needed.
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;
}
I am trying to display detailed Product information in an custom Listview with two TextViews per row for the key/value pair. The data is displayed correct. I also colored every second line different.
And there is my Problem. If I scroll up and down the different colored rows change their color and remain in this state. The data is not affected from this problem. Just the backroundcolor of the TextViews. I use the ViewHolder Pattern but this did not change anything. I added the code of the adapter. I think thats enough. Have you any idea?
Screenshot of the problem:
Code:
public class ProductDetailAdapter extends BaseAdapter {
private LinkedHashMap<String,String> list;
private Context context;
public ProductDetailAdapter(Context c, LinkedHashMap<String,String> list){
super();
this.context = c;
this.list=list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ProductDetailAdapter.ViewHolder viewHolder;
if(convertView == null){
convertView=inflater.inflate(R.layout.product_detail_data_row,null);
viewHolder = new ViewHolder();
viewHolder.textViewKey = (TextView) convertView.findViewById(R.id.productDataKey);
viewHolder.textViewValue = (TextView) convertView.findViewById(R.id.productDataValue);
convertView.setTag(viewHolder);
}else {
viewHolder = (ProductDetailAdapter.ViewHolder) convertView.getTag();
}
viewHolder.textViewKey.setText((String)list.keySet().toArray()[position]);
viewHolder.textViewValue.setText(list.get(list.keySet().toArray()[position]));
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
}
return convertView;
}
private static class ViewHolder {
public TextView textViewKey;
public TextView textViewValue;
public ViewHolder(){};
}
}
That happens because the rows are being recycled. It's a common problem.
You can solve it by doing:
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
} else {
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
}
Try this:
super( c, 0, list );
instead of this:
super();
Once you pass the data source to the adapter you no longer need :
getCount
getItem
getItemId
please refer this link and link2 and link3 these will work for you
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.
I making a gridview that is made of a text and under it an image and everything is working fine but the problem is that when I scroll, the images gets repeated, so any tips on how I could solve this problem
here is my adapter:
public class CustomGridAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
public CustomGridAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from mobile.xml
gridView = inflater.inflate(R.layout.heartless_gridview_design, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.heartless_name);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.heartless_image);
String mobile = mobileValues[position];
if (mobile.equals("Shadow")) {
imageView.setImageResource(R.drawable.shadow);
} else if (mobile.equals("Soldier")) {
imageView.setImageResource(R.drawable.soldier);
} else if (mobile.equals("Large Body")) {
imageView.setImageResource(R.drawable.large_body);
} else if (mobile.equals("Silver Rock")) {
imageView.setImageResource(R.drawable.silver_rock);
} else if (mobile.equals("Emerald Blues")) {
imageView.setImageResource(R.drawable.emerald_blues);
} else {
}
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return mobileValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
please if you know how to fix this please tell me how.
so far I understood you should use viewholder pattern and
every time when getView method calls check if viewholder is null initialize it otherwise do nothing just return view..
http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder
and good example here - http://java.dzone.com/articles/android-listview-optimizations