Now i should implement infinite scrolling to listview, for this i had found one easiest code that is
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//leave this empty
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (listView.getLastVisiblePosition() >= listView.getCount() - threshold) {
currentPage++;
//load more list items:
loadElements(currentPage);
}
}
}
but now i dont know what to include in the place if loadElements(current Page)
Here is an example code for you. this list scrolls infinite and using thread, it scrolls automatically. (pauses for while and coninues ...)
When you touch the list, list scrolling pauses and when you release it continues to automatic scroll.
If you touch under 100 miliseconds then it will considered item on click.
You can also scroll down or up, it will eventually continue to auto scrolling.
Come to think of it, it has turn into web like list. shame. :(
///////////////////////////////////////////////////////////////////////
List Item XML layout : item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:orientation="vertical" >
<TextView
android:background="#00ff00"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:id="#+id/name"
android:textColor="#000000"
android:textSize="26sp"
android:gravity="center"
android:textStyle="bold"/>
</LinearLayout>
///////////////////////////////////////////////////////////////////////
activity layout : activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="25dp"
android:gravity="center"
tools:context=".MainActivity" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="450dp"
android:background="#bbbbbb"
android:divider="#000000"/>
</RelativeLayout>
///////////////////////////////////////////////////////////////////////
activiy code (includes adapter and runnable thread) : MainActivity.java
public class MainActivity extends Activity {
ListView list;
long startTime;
long endTime;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView) findViewById(R.id.list);
List<String> mList = new ArrayList<String>();
String str;
for(int i=0;i<10;i++){
str = new String("Data --- "+i);
mList.add(str);
}
LAdapter adapter = new LAdapter(this,0,mList);
list.setAdapter(adapter);
final YourRunnable runy = new YourRunnable();
list.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN ){
startTime= (new Date()).getTime();
runy.onPause();//pausing thread actually pauses scrolling
}
if(event.getAction() == MotionEvent.ACTION_UP){
endTime= (new Date()).getTime();
if((endTime - startTime)<=100){//100 mill second limit for click
//Log.i("ITEM CLICK() ", "item : ");
}
runy.onResume(); //resume scrolling
}
return false;
}
});
new Thread(runy).start();
}
class YourRunnable implements Runnable {
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;
public YourRunnable() {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
}
public void run() {
while (!mFinished) {
//for loop is not infinite but enough as Integer.MAX_VALUE
for (int index = 0; index < list.getAdapter().getCount(); index++) {
list.smoothScrollToPositionFromTop(list.getLastVisiblePosition() + 1, 0, 10000);
try {
// it helps scrolling to stay smooth as possible (by experiment)
Thread.sleep(10000);
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();//putting thread in wait list of mPauseLock object
} catch (InterruptedException e) {
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* Call this method to pause thread.
*/
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
/**
* Call this method to resume thread.
*/
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();//notify all object that are waiting on the wait list of mPauseLock object
}
}
}
private class LAdapter extends ArrayAdapter{
List<String> mlist;
Context mContext;
LayoutInflater inflater;
public final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
public final int MIDDLE;
public LAdapter(Context ctx,int resId, List<String> objects){
super(ctx, resId, objects);
mContext = ctx;
mlist = objects;
inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % mlist.size();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
int relativePos = position % mlist.size();
Log.i("RELATIVE : "," POS:"+relativePos);
return mlist.get(relativePos);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Log.i("POSITION TAG", "POSITION : "+position);
// if(position>(getCount()-1)){
// return null;
// }
ViewHolder holder = null;
if (convertView == null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, parent, false);
holder.name = (TextView) convertView.findViewById(R.id.name);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
String model = getItem(position);
holder.name.setText(model);
convertView.setOnClickListener(new ListenerT(model) {
#Override
public void onClick(View v) {
Log.i("CLICK", "ITEM---"+name );
}
});
return convertView;
}
}
//use your own listener to pass parameter
private class ListenerT implements OnClickListener{
String name;
public ListenerT(String nm){
name = nm;
}
#Override
public void onClick(View v) {
}
}
private class ViewHolder{
TextView name;
}
}
Related
I use this code to update the listview of my project but i get duplicates by using the listview.invalidateViews(); method. Also i tried the notifyDataSetChanged method by calling it from the customadapter of mine that extends baseadapter but it does not seem to work properly. I need to update using the postexecute method after downloading the data from online source. Please check below my code.
The HomeFragment
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
Bitmap mIcon12;
private ProgressDialog pDialog;
private ArrayList< String> arrayList;
ArrayList<HashMap<String,String>> aList;
private int scrollState;
private int offset = 0;
private Button btnLoadMore;
private boolean flag = false;
private boolean loadingMore = false;
TextView textinput2;
ImageView lv1;
View root;
View root1;
ProgressBar pb;
private int scrollpos;
private ListView lv;
public ArrayList<SubjectData> arrayList1;
CustomAdapter adapter1;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container,Bundle savedInstanceState) {
homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
root = inflater.inflate(R.layout.fragment_home, container, false);
root1 = inflater.inflate(R.layout.listitem, container, false);
final TextView textView = root.findViewById(R.id.text_home);
lv = root.findViewById(R.id.homelistview);
lv1=root1.findViewById(R.id.flagimageview);
arrayList1 = new ArrayList<SubjectData>();
lv.setClickable(true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object o = lv.getItemAtPosition(position);
Toast.makeText(getContext(), "myPosss "+position, Toast.LENGTH_LONG).show();
}
});
MainActivity main1 = (MainActivity)getActivity();
if (savedInstanceState == null) {
adapter1 = new CustomAdapter(getContext(), arrayList1);
System.out.println("to lv den ine null edopoooooooooooo");
} else {
}
pb = new ProgressBar(getContext());
lv.addFooterView(pb);
lv.setAdapter(adapter1);
if (!flag) {
new loadMoreListView().execute();
flag = true;
System.out.println("to flag1 ine: "+ flag);
}
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
scrollpos = totalItemCount;
int lastPos = firstVisibleItem + visibleItemCount;
if ((lastPos == totalItemCount) && (!loadingMore)) {
if (totalItemCount < 250) {
System.out.println("to flag4 ine " + flag);
new loadMoreListView().execute();
} else {
lv.removeFooterView(pb);
}
}
}
});
homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
private class loadMoreListView extends AsyncTask< Void, Void, String> {
protected String doInBackground(Void... unused) {
loadingMore = true;
String result = null;
String url = "https://api.androidhive.info/json/imdb_top_250.php?offset=" + offset;
try {
URL mUrl = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
urlConnection.setConnectTimeout(10000); //set timeout to 5 seconds
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer buffer = new StringBuffer();
String str = "";
while ((str = br.readLine()) != null) {
buffer.append(str);
}
result = buffer.toString();
} catch (Exception e) {
System.out.println("error " + e);
}
return result;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
public class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
#Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
return vi;
}
protected void onPostExecute(String result) {
if (result != null) {
try {
JSONArray array = new JSONArray(result);
for (int i = 0; i < array.length(); i++) {
arrayList1.add(new SubjectData(array.getJSONObject(i).getString("title"),"link", "image"));
}
loadingMore = false;
System.out.println("to flag2 ine: "+ flag);
lv.invalidateViews();
// adapter1.updater(arrayList1);
offset+=20;
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (pb==null)
{
System.out.println("ine null to pb ");
}
else if (lv==null) {
pb.setVisibility(pb.GONE);
Toast.makeText(getContext(), "Please check your internet connection!", Toast.LENGTH_SHORT).show();
pb=null;
}
else
{
lv.removeFooterView(pb);
}
}
}
}
}
And this is the customadapter that extends the baseadapter
public class CustomAdapter extends BaseAdapter {
public ArrayList<SubjectData> arrayList;
Context context;
Thread t;
public CustomAdapter(Context context, ArrayList<SubjectData> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public void updater(ArrayList<SubjectData> updatedlist)
{
this.arrayList.clear();
this.arrayList.addAll(updatedlist);
this.notifyDataSetChanged();
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return true;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return false;
}
public View getView(int position, View convertView, ViewGroup parent) {
SubjectData subjectData = arrayList.get(position);
if(convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.listitem, null);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity activity= (AppCompatActivity)context;
ImageView image = new ImageView(context);
image.setImageResource(R.drawable.notificationstoreicon);
final ProgressBar pb = new ProgressBar(context);
String[] coupons = {"horse", "cow", "camel", "sheep", "goat"};
AlertDialog.Builder builder =
new AlertDialog.Builder(context).
setTitle("Details").
setView(pb).
setMessage("please wait...")
.
setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// dialog.dismiss();
if (t.isAlive())
{
}
else
{
}
}
});
AlertDialog dialog1=builder.create();
dialog1.show();
t= new Thread()
{ private volatile boolean running = true;
public void run() {
System.out.println("blah");
while (running) {
try {
// thread to sleep for 1000 milliseconds
Thread.sleep(4000);
running=false;
} catch (Exception e) {
System.out.println(e);
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
dialog1.setMessage("more details");
pb.setVisibility(View.GONE);
Picasso.get()
.load(subjectData.Image)
.into(image);
dialog1.setContentView(image);
}
});
}
public void stopThread() {
running = false;
interrupt();
}
public void runOnUiThread(Runnable runnable){
final Handler UIHandler = new Handler(Looper.getMainLooper());
UIHandler.post(runnable);
}
};
t.start();
}
});
TextView tittle = convertView.findViewById(R.id.txt);
ImageView imag = convertView.findViewById(R.id.flagimageview);
tittle.setText(subjectData.SubjectName);
Picasso.get()
.load(subjectData.Image)
.into(imag);
}
return convertView;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
if(getCount() > 0){
return arrayList.size();
}else{
return 1;
}
}
#Override
public boolean isEmpty() {
return false;
}
}
Fragment home xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<TextView
android:id="#+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Please check your internet connection!"
android:textAlignment="center"
android:textSize="20sp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="invisible" />
<ListView
android:id="#+id/homelistview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/helloimageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="productimage"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Any help appreciated. I searched in other people posts but no luck! I have been searching for hours actually!
Can anyone help me? Cant find solution!
I'm trying to make a GridView full of checkboxes. I'm following the ViewHolder pattern to recycle views and attempt to set checkboxes to their correct values, but for some reason I can't seem to make them not duplicate.
After my debugging efforts, I've discovered that my SparseBooleanArray IS being correctly updated - it's just that applying it to the view seems to turn on the wrong checkboxes even when I'm applying them to the right positions.
Here's my GridView's entire adapter - relevant portions being getView and onCheckedChanged
// Our image adapter takes our list of thumbnails and creates a selectable grid full of asychroniously loaded images.
public class ThumbnailImageAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener {
Context mContext;
LayoutInflater mInflater;
SparseBooleanArray mCheckedStates;
private int mItemHeight = 0;
private int mNumColumns = 0;
private RelativeLayout.LayoutParams mImageViewLayoutParams;
private ArrayList<String> mList;
private ArrayList<String> mImageFullResUrls;
private String nextURL;
public ThumbnailImageAdapter(Context context) {
super();
mContext = context;
mInflater = LayoutInflater.from(mContext);
mImageViewLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
clear();
}
public ArrayList<String> getCheckedItems() {
ArrayList<String> checkedItems = new ArrayList<String>();
for (int i = 0; i < mList.size(); i++) {
if (mCheckedStates.get(i)) {
checkedItems.add(mImageFullResUrls.get(i));
}
}
return checkedItems;
}
public boolean hasSelectedItems() {
return mCheckedStates.indexOfValue(true) >= 0;
}
#Override
public int getCount() {
// If columns have yet to be determined, return no items
if (getNumColumns() == 0) {
return 0;
}
return mList.size();
}
#Override
public Object getItem(int position) {
return mImageFullResUrls.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public View getView(int position, View convertView, ViewGroup container) {
if(position >= getCount()) {
return null;
}
final ThumbnailViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.selectable_imageview, null);
holder = new ThumbnailViewHolder();
holder.checkbox = (CheckBox) convertView.findViewById(R.id.photo_checkbox);
holder.imageView = (SmartImageView) convertView.findViewById(R.id.photo_imageview);
convertView.setTag(holder);
} else {
holder = (ThumbnailViewHolder) convertView.getTag();
}
holder.checkbox.setTag(position);
holder.checkbox.setOnCheckedChangeListener(this);
holder.checkbox.setChecked(mCheckedStates.get(position, false));
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
holder.imageView.setImageUrl(mList.get(position));
final View finalView = convertView;
convertView.post(new Runnable() {
#Override
public void run() {
Rect delegateArea = new Rect();
holder.imageView.getHitRect(delegateArea);
finalView.setTouchDelegate(new TouchDelegate(delegateArea, holder.checkbox));
}
});
return convertView;
}
public void setItemHeight(int height) {
if (height == mItemHeight) {
return;
}
mItemHeight = height;
mImageViewLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, mItemHeight);
notifyDataSetChanged();
}
public int getNumColumns() {
return mNumColumns;
}
public void setNumColumns(int numColumns) {
mNumColumns = numColumns;
}
public void appendImage(String thumbUrl, String fullResUrl) {
if (!mList.contains(thumbUrl)) {
mList.add(thumbUrl);
mImageFullResUrls.add(fullResUrl);
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}
}
public void prependImage(String thumbUrl, String fullResUrl) {
if (!mList.contains(thumbUrl)) {
mList.add(0, thumbUrl);
mImageFullResUrls.add(0, fullResUrl);
SparseBooleanArray shiftedArray = new SparseBooleanArray(mList.size());
// Shift our entire array one down (there has to be a better way to do this)
for (int i = 0; i < mCheckedStates.size(); i++) {
shiftedArray.put(mCheckedStates.keyAt(i) + 1, mCheckedStates.valueAt(i));
}
mCheckedStates = shiftedArray;
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}
public void clear() {
mList = new ArrayList<String>();
mImageFullResUrls = new ArrayList<String>();
mCheckedStates = new SparseBooleanArray();
}
public String getNextURL() {
return this.nextURL;
}
public void setNextURL(String nextURL) {
this.nextURL = nextURL;
}
public ArrayList<String> getThumbnailURLs() {
return mList;
}
#Override
public void onCheckedChanged(CompoundButton checkBoxView, boolean isChecked) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
final int numPhotos = Integer.parseInt(settings.getString("num_photos", null));
if (mAdapter.getCheckedItems().size() > numPhotos) {
checkBoxView.setChecked(false); // Don't allow the user to select more than numPhotos photos
}
// This animates our image "pressed" and "unpressed" states
mCheckedStates.put((Integer) checkBoxView.getTag(), isChecked);
final ImageView image = (ImageView) ((ViewGroup) checkBoxView.getParent()).findViewById(R.id.photo_imageview);
int dpi = getResources().getDisplayMetrics().densityDpi;
int _12dp = (int) (12 * (dpi / 160f));
ValueAnimator animator;
if (isChecked) {
animator = ValueAnimator.ofInt(image.getPaddingRight(), _12dp);
} else {
animator = ValueAnimator.ofInt(image.getPaddingRight(), 0);
}
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int v = (Integer) valueAnimator.getAnimatedValue();
image.setPadding(v, v, v, v);
}
});
animator.setDuration(100);
animator.start();
mOnImageSelectionChangeListener.onImageSelectionChange(getCheckedItems());
getActivity().invalidateOptionsMenu();
}
}
static class ThumbnailViewHolder {
CheckBox checkbox;
SmartImageView imageView;
}
This is due to the way grid view recycles view's.
Implement the below for your adapter
implements CompoundButton.OnCheckedChangeListener
Then have a SpareBooleanArray to keep track of checked stated
SparseBooleanArray mCheckStates;
Then
mCheckStates = new SparseBooleanArray(your data size);
In getView
holder.chkSelect.setTag(position);
holder.chkSelect.setChecked(mCheckStates.get(position, false));
holder.chkSelect.setOnCheckedChangeListener(this);
Then override
public boolean isChecked(int position) {
return mCheckStates.get(position, false);
}
public void setChecked(int position, boolean isChecked) {
mCheckStates.put(position, isChecked);
}
public void toggle(int position) {
setChecked(position, !isChecked(position));
}
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mCheckStates.put((Integer) buttonView.getTag(), isChecked);
}
Also move this
holder.imageView = (SmartImageView) convertView.findViewById(R.id.photo_imageview);
to the if part in getView
and change this
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
imageView.setImageUrl(mList.get(position));
to
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
holder.imageView.setImageUrl(mList.get(position));
You can find a similar exmaple #
How to get checkbox state in a gridview
I have an Vertical listview i want listview should be closed. For example if the last item is reached in Listview then show the first item below the last item. It means item should be in circular format. And if i scroll from first item it should show last item before first item. I want scrolling for both side.
public class MainActivity extends Activity {
ListView list;
long startTime;
long endTime;
List<String> mList = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView) findViewById(R.id.list);
downloadDetails();
String str;
for (int i = 0; i < 10; i++) {
str = new String("Data --- " + i);
mList.add(str);
}
CircularAdapter adapter = new CircularAdapter(this, 0, mList);
list.setAdapter(adapter);
final YourRunnable runy = new YourRunnable();
list.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
startTime = (new Date()).getTime();
runy.onPause();// pausing thread actually pauses scrolling
}
if (event.getAction() == MotionEvent.ACTION_UP) {
endTime = (new Date()).getTime();
if ((endTime - startTime) <= 100) {// 100 mill second limit
// for click
// Log.i("ITEM CLICK() ", "item : ");
}
runy.onResume(); // resume scrolling
}
return false;
}
});
new Thread(runy).start();
}
class YourRunnable implements Runnable {
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;
public YourRunnable() {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
}
#SuppressLint("NewApi")
public void run() {
while (!mFinished) {
// for loop is not infinite but enough as Integer.MAX_VALUE
for (int index = 0; index < list.getAdapter().getCount(); index++) {
list.smoothScrollToPositionFromTop(list.getLastVisiblePosition() + 1, 0, 10000);
try {
// it helps scrolling to stay smooth as possible (by
// experiment)
Thread.sleep(3000);
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();// putting thread in wait
// list of mPauseLock
// object
} catch (InterruptedException e) {
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// to pause list
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
// resume thread
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();// notify all object that are waiting on
// the wait list of mPauseLock object
}
}
}
private class CircularAdapter extends ArrayAdapter {
List<String> mlist;
Context mContext;
LayoutInflater inflater;
public final int HALF_MAX_VALUE = Integer.MAX_VALUE / 2;
public final int MIDDLE;
#SuppressWarnings("unchecked")
public CircularAdapter(Context ctx, int resId, List<String> objects) {
super(ctx, resId, objects);
mContext = ctx;
mlist = objects;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % mlist.size();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
int relativePos = position % mlist.size();
Log.i("RELATIVE : ", " POS:" + relativePos);
return mlist.get(relativePos);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, parent, false);
holder.name = (TextView) convertView.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String model = getItem(position);
holder.name.setText(model);
convertView.setOnClickListener(new ListenerT(model) {
#Override
public void onClick(View v) {
Log.i("CLICK", "ITEM---" + name);
}
});
return convertView;
}
}
// use your own listener to pass parameter
private class ListenerT implements OnClickListener {
String name;
public ListenerT(String nm) {
name = nm;
}
#Override
public void onClick(View v) {
}
}
private class ViewHolder {
TextView name;
}
}
I have a Spinner on my Activity. I use an ArrayList and a custom SpinnerAdapter to populate the list that pops up when the Spinner is pressed.
My problem is the way the Spinner looks on the Activity when it is not pressed. It is all gray. No text is visible. Even after I press the spinner and then choose an item from the resulting list, the Spinner does not populate with text.
Also, when I select an item from the Spinner and then print the selected item position, it prints -1. Many have commented that there is no list of data attached to my spinner, but there obviously is. How else could I press on the Spinner and then choose from a resulting list?
// This sets up the adapter and the arraylist that contains the data
private void setUpAdapter() {
mData = new ArrayList<MyData>();
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
// this populates the arraylist that is attached to the spinner's adapter
// it is called once an AsyncTask finishes pulling data from a local database
private void populateSpinner(ArrayList<MyData> result) {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mSpinner.setSelected(0);
}
}
// this is the adapter for the spinner
private class MyAdapter implements SpinnerAdapter {
ArrayList<MyData> data;
public MyAdapter(ArrayList<MyData> data){
this.data = data;
}
#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;
}
#Override
public int getItemViewType(int position) {
return android.R.layout.simple_spinner_dropdown_item;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(getApplicationContext());
v.setTextColor(Color.BLACK);
v.setText(data.get(position).getName());
v.setPadding(0, 20, 0, 20);
return v;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return this.getView(position, convertView, parent);
}
}
<Spinner
android:id="#+id/my_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
When I select an item from the Spinner and then print the selected item position, it prints -1
This is because you are referencing BLANK list
mData = new ArrayList<MyData>();
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
Set spinner adapter in onPostExecute() of AsynTask.
#Override
protected void onPreExecute() {
mData = new ArrayList<MyData>();
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
//gets "result" to fill mData
return null;
}
#Override
protected void onPostExecute(Void result) {
setUpAdapter();
}
private void setUpAdapter() {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
mSpinner.setSelected(0);
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
Use Activity context instead of the Application context for your spinner. See documentation of getApplicationContext() api to understand its proper usage.
Pass the activity context to MyAdapter and use it in creating the TextView's in getView callback.
mAdapter = new MyAdapter(mData, this); // this is activity context.
In MyAdapter :
public MyAdapter(ArrayList<MyData> data, Context context){
this.data = data;
mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(mContext);
v.setTextColor(Color.BLACK);
v.setBackgroundColor(Color.WHITE);
v.setText(data.get(position).getName());
v.setPadding(0, 20, 0, 20);
return v;
}
You can set static sizes using the xml attribute android:layout_height.
Using dp unit instead of px is recommended for multiple screen compatibility.
As for the text, try to use android:prompt attribute in your Spinner xml. For the color I'm guessing it's like other widgets, just use android:textColor
THIS code is WORKING, the spinner correctly display the field, however i must say maybe it is not 100% perfect, cause for some reason im unable to leave blank the initial value of the field, it has by default the value of item 0.
package com.cccheck;
public class OneCheckActivity extends Activity {
LayoutInflater factory;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spinner_view);
ArrayList tdata = new ArrayList<MyData>();
MyData mdata =new MyData();
mdata.setName("");
mdata.setData("-1");
MyData ndata =new MyData();
ndata.setName("ciao belluzzo");
ndata.setData("1");
tdata.add(mdata);
tdata.add(ndata);
mdata= new MyData();
mdata.setName("vai alla fnac");
mdata.setData("2");
tdata.add(mdata);
mSpinner = (Spinner) findViewById(R.id.my_spinner);
factory = LayoutInflater.from(this);
populateSpinner(tdata);
setUpAdapter();
mSpinner.setSelected(false);
try {
mAdapter.notify();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//mAdapter.registerDataSetObserver(new MyObserver());
}
ArrayList<MyData> mData;
MyAdapter mAdapter = new MyAdapter(null);
Spinner mSpinner;
// This sets up the adapter and the arraylist that contains the data
private void setUpAdapter() {
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
Toast.makeText(OneCheckActivity.this , "selected item : " + pos + ", value: " + g.getData(),Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
// this populates the arraylist that is attached to the spinner's adapter
//it is called once an AsyncTask finishes pulling data from a local database
private void populateSpinner(ArrayList<MyData> result) {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
}
}
// this is the adapter for the spinner
private class MyAdapter implements SpinnerAdapter {
ArrayList<MyData> data;
public MyAdapter(ArrayList<MyData> data){
this.data = data;
}
public void updateData(ArrayList<MyData> data){
this.data = data;
}
#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;
}
#Override
public int getItemViewType(int position) {
return android.R.layout.simple_spinner_dropdown_item;
}
#Override
public LinearLayout getView(int position, View convertView, ViewGroup parent) {
LinearLayout pv = (LinearLayout)(factory.inflate(R.layout.spinner_item, null));
TextView tv = (TextView) pv.findViewById(R.id.textviewid);
tv.setTextColor(Color.BLACK);
MyData item = data.get(position);
tv.setText( item.getName() + " - " + item.getData() + " ");
tv.setPadding(0, 20, 0, 20);
return pv;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return data.isEmpty();
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public LinearLayout getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView instanceof LinearLayout) System.out.println("%%%%%%%%%%%%%%55555 hai ragione");
return this.getView(position, convertView, parent);
}
}
}
use this as layout for spinner_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="28px"
android:id="#+id/textviewid"
/>
</LinearLayout>
I'm trying to update the TextView within a custom ListView at a set time interval, for example the TextView will update every 200ms however I can't figure out how to do this. The object updates with a number internally and I would like to show that in the mTitleText Textview however as the code below shows at the moment I can only achieve it when the user presses a button.
public class ListAdapter extends BaseAdapter {
private ArrayList< Object > mObjects;
private int mNumObjs = 0;
private LayoutInflater mLayoutInflater;
private Context mContext;
public ListAdapter ( Context context, ArrayList< Object > objects ) {
mObjects;= objects;
mLayoutInflater = LayoutInflater.from(context);
mContext = context;
}
public int getCount() {
return mObjects;.size();
}
public Object getItem( int position ) {
return mObjects;.get(position);
}
public long getItemId( int position ) {
return position;
}
public void addObject( Object obj) {
obj.setId(mNumObjs);
mObjects.add( obj );
(mNumObjs);++;
notifyDataSetChanged();
}
public void deleteObject( int pos ) {
mObjects;.remove( pos );
notifyDataSetChanged();
}
public View getView( final int position, View convertView, ViewGroup parent ) {
final TimerView holder;
if( convertView == null ) {
convertView = mLayoutInflater.inflate( R.layout.customlistview, null );
holder = new HolderView();
holder.mListPosition = position;
holder.mDeleteButton = (Button)convertView.findViewById(R.id.Delete);
holder.mDeleteButton.setText( "Button No: " + position );
holder.mDeleteButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
deleteObject(holder.mListPosition);
}
});
holder.mButton = (Button)convertView.findViewById(R.id.Button);
holder.mButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Object obj = mObjects.get(holder.mListPosition);
mTitleText.setText(obj.getNum());
}
});
convertView.setTag(holder);
}
else {
holder = (TimerView) convertView.getTag();
}
holder.mListPosition = position;
holder.mDeleteButton.setText( "Button No: " + position );
return convertView;
}
class HolderView{
int mListPosition;
Button mDeleteButton;
Button mButton;
TextView mTitleText;
}
}
Okay I managed to figure this out myself, if your updates don't need to be very frequent ( >1 sec ) you can use notifyDataSetChanged() however if like me you need to constantly update the listview every 200ms or so you need to iterate through the visible objects on the list view and update it.
private Runnable showUpdate = new Runnable(){
public void run(){
mAdapter.updateList();
//mAdapter.notifyDataSetChanged();
int count = mListView.getCount();
for( int i = 0; i < count; i ++ )
{
View convertView = mListView.getChildAt( i );
if( convertView != null )
{
HolderView holder = (HolderView) convertView.getTag();
Object obj = (Object)mAdapter.getItem( holder.mListPosition );
holder.mTitleText.setText( obj.getText() );
}
}
}
};
Thread mThread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(100);
mHandler.post(showUpdate);
//mHandler.sendEmptyMessage(MSG_UPDATE);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Update the text in your list mObjects and call notifyDataSetChanged() on your adapter.