Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView - ImageLoader moves List / Items on Scroll up

I'm looking for an answer half a day, but I can't find anything although I thought it is a common problem. My Problem: I have a ListView which has items of different sizes (heights). Every item contains an ImageView. The Image for this ImageView is loaded in background by an ImageLoader class:

imageLoader.DisplayImage(url, holder.image);

If i scroll down the ListView everything works fine. the images are loaded and display (of course at the bottom of the screen / list).

But If I scroll up and the image isn't stored in cache anymore, so the ImageLoader has to reload the image, the ListView jumps / the items are moved. I think it is because a new View is created on top of the list, with an ImageView with 0dp height. If the Image is loaded and set to the ImageView the height of the ImageView changes automatically from 0dp to the size of the Image. This would push the ListView down, I think.

I tried saving the height of the ImageViews if an Image is set and then set the height of the ImageView which is created on top to the saved height. But with no success..

I don't know if you can understand my problem :D I hope so :)

Thanks and have a nice day!

EDIT: Added ImageLoader Class

public class ImageLoader {

MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
int size;
Context context;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
private HashMap<String, Integer> imagesSizes; 
ExecutorService executorService;
Handler handler=new Handler();//handler to display images in UI thread

public ImageLoader(Context context, int size){
    fileCache=new FileCache(context);
    this.context = context;
    executorService=Executors.newFixedThreadPool(5);
    this.size = size;
    imagesSizes = new HashMap<String, Integer>();
}

final int stub_id=R.color.transparent;
public void DisplayImage(String url, ImageView imageView)
{
    imageViews.put(imageView, url);
    Bitmap bitmap=memoryCache.get(url);
    if(bitmap!=null){
        imageView.setImageBitmap(bitmap);
        saveImageSize(imageView, url);
    }   
    else
    {
        queuePhoto(url, imageView);
        imageView.setImageResource(stub_id);
        setImageSize(imageView, url);
    }
}

public void DisplayImage(File file, ImageView imageView)
{
    imageViews.put(imageView, file.getAbsolutePath());
    Bitmap bitmap=memoryCache.get(file.getAbsolutePath());
    if(bitmap!=null){
        imageView.setImageBitmap(bitmap);
        saveImageSize(imageView, file.getAbsolutePath());
    } 
    else
    {
        queuePhoto(file, imageView);
        imageView.setImageResource(stub_id);
        setImageSize(imageView, file.getAbsolutePath());
    }
}

private void saveImageSize(ImageView imageView, String url){

    int height = imageView.getHeight();
    imagesSizes.put(url, height);
    System.out.println("IMAGE SIZE: Save: " + url + "  " + height );
}

private void setImageSize(ImageView imageView, String url){
    if(imageView != null && imagesSizes!=null && imagesSizes.containsKey(url)){
        imageView.getLayoutParams().height = imagesSizes.get(url);
        imageView.requestLayout();
        System.out.println("IMAGE SIZE: Set: " + url + "  " + imagesSizes.get(url) );
    }
}


private void queuePhoto(String url, ImageView imageView)
{
    PhotoToLoad p=new PhotoToLoad(url, imageView);
    executorService.submit(new PhotosLoader(p));
}

private void queuePhoto(File file, ImageView imageView)
{
    PhotoToLoad p=new PhotoToLoad(file, imageView);
    executorService.submit(new PhotosLoader(p));
}

public Bitmap getImage(String url){
    return getBitmap(url);
}

private Bitmap getBitmap(String url) 
{
    File f=fileCache.getFile(url);

    //from SD cache
    Bitmap b = decodeFile(f);
    if(b!=null)
        return b;

    //from web
    try {
        Bitmap bitmap=null;
        URL imageUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        conn.setInstanceFollowRedirects(true);
        InputStream is=conn.getInputStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        conn.disconnect();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Throwable ex){
       ex.printStackTrace();
       if(ex instanceof OutOfMemoryError)
           memoryCache.clear();
       return null;
    }
}

//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
    try {
        //decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        FileInputStream stream1=new FileInputStream(f);
        BitmapFactory.decodeStream(stream1,null,o);
        stream1.close();

        //Find the correct scale value. It should be the power of 2.
        final int REQUIRED_SIZE=size;
        int width_tmp=o.outWidth, height_tmp=o.outHeight;
        int scale=1;
        while(true){
            if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                break;
            width_tmp/=2;
            height_tmp/=2;
            scale*=2;
        }

        //decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        FileInputStream stream2=new FileInputStream(f);
        Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
        stream2.close();
        return bitmap;
    } catch (FileNotFoundException e) {
    } 
    catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

//Task for the queue
private class PhotoToLoad
{
    public File file;
    public String url;
    public ImageView imageView;
    public PhotoToLoad(String u, ImageView i){
        url=u; 
        imageView=i;
        file = null;
    }

    public PhotoToLoad(File file, ImageView i){
        url=file.getAbsolutePath(); 
        imageView=i;
        this.file = file;
    }
}

class PhotosLoader implements Runnable {
    PhotoToLoad photoToLoad;
    PhotosLoader(PhotoToLoad photoToLoad){
        this.photoToLoad=photoToLoad;
    }

    @Override
    public void run() {
        try{
            if(imageViewReused(photoToLoad))
                return;
            Bitmap bmp;
            if(photoToLoad.file== null){
                bmp=getBitmap(photoToLoad.url);
            } else {
                bmp=decodeFile(photoToLoad.file);
            }
            memoryCache.put(photoToLoad.url, bmp);
            if(imageViewReused(photoToLoad))
                return;
            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
            handler.post(bd);
        }catch(Throwable th){
            th.printStackTrace();
        }
    }
}

boolean imageViewReused(PhotoToLoad photoToLoad){
    String tag=imageViews.get(photoToLoad.imageView);
    if(tag==null || !tag.equals(photoToLoad.url))
        return true;
    return false;
}

//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
    Bitmap bitmap;
    PhotoToLoad photoToLoad;
    public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
    public void run()
    {
        if(imageViewReused(photoToLoad))
            return;
        if(bitmap!=null)
            photoToLoad.imageView.setImageBitmap(bitmap);
        else
            photoToLoad.imageView.setImageResource(stub_id);
        if(photoToLoad.file== null){
            setImageSize(photoToLoad.imageView, photoToLoad.url);
        } else {
            setImageSize(photoToLoad.imageView, photoToLoad.file.getAbsolutePath());
        }

    }
}



public void clearCache() {
    memoryCache.clear();
    fileCache.clear();
}

EDIT: Added Adapter:

 public class LazyNewPostsAdapter extends BaseAdapter implements Constants{

private Activity activity;
private ArrayList<Image> data;
private static LayoutInflater inflater=null;
private ImageLoader imageLoader; 
private AsyncHelper helper;
public static final int VIEW_TYPE_LOADING = 0;
public static final int VIEW_TYPE_ACTIVITY = 1;

private int imgposition;
Handler fmHandler = null;

Handler handler = new Handler(){
    public void handleMessage(android.os.Message msg) {
        switch(msg.what){
        case HANDLER_NEW_POST_VOTE_IMAGE:
                int position = msg.arg1;
            JSONObject json;
            try {
                json = new JSONObject((String) msg.obj);

                int success =  json.getInt("success");

                if(success == 1){

                    int i_id = json.getInt("i_id");
                    int votesUp = json.getInt("votes_up");
                    int votesDown = json.getInt("votes_down");

                    data.get(position).setVotesUp(votesUp);
                    data.get(position).setVotesDown(votesDown);
                    notifyDataSetChanged();
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }   

            break;
        case HANDLER_USER_REPORTED_IMAGE:
            JSONObject json2 = Utils.createJSON((String)msg.obj);
            System.out.println("REPORT IMAGE " + json2);
            if(json2 != null){
                try {
                    int success = json2.getInt("success");
                    if(success==1){
                         Toast.makeText(activity, "Image reported!", Toast.LENGTH_LONG).show();

                    }
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            break;
        case HANDLER_IMAGE_SIZE_AVAILABLE:
            String url = (String) msg.obj;
            int height = msg.arg1;
            int width = msg.arg2;

            int imgPosition = findImageOfCertainURL(url);
            System.out.println("GETVIEW HANDLER 1: IMAGE POSITION" + imgPosition);

            if(imgPosition != -1){
                data.get(imgPosition).setHeight(height);
                data.get(imgPosition).setWidth(width);
            }
            Message copyMsg = new Message();
            copyMsg.what = HANDLER_IMAGE_SIZE_AVAILABLE;
            copyMsg.arg1 = height;
            copyMsg.arg2 = width;
            copyMsg.obj = url;
            fmHandler.sendMessage(copyMsg);
            notifyDataSetChanged();
            break;
        }
    };
};

private int findImageOfCertainURL(String url){
    for(int i = 0; i <data.size();i++){
        if((URL_FOLDER_IMAGES + data.get(i).getUrl()).equalsIgnoreCase(url)){
            return i;
        }
    }
    return -1;
}

public LazyNewPostsAdapter(Activity a, ArrayList<Image> d, Handler fragmentHandler) {

    activity = a;

    data=d;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    helper =  new AsyncHelper(activity, handler);

    imageLoader=new ImageLoader(activity.getApplicationContext(), 600,handler) ;
    fmHandler = fragmentHandler;
}

public void updateData(ArrayList<Image> d){
    data = d;
    notifyDataSetChanged();
}



public int getCount() {
    return data.size()+1;
}

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    // TODO Auto-generated method stub
    return (position >= data.size()) ? VIEW_TYPE_LOADING
            : VIEW_TYPE_ACTIVITY;
}

@Override
public boolean isEnabled(int position) {
    return getItemViewType(position) == VIEW_TYPE_ACTIVITY;
}

public Object getItem(int position) {
    return (getItemViewType(position) == VIEW_TYPE_ACTIVITY) ? data.get(position) : null;
}

public long getItemId(int position) {
    return (getItemViewType(position) == VIEW_TYPE_ACTIVITY) ? position
            : -1;
}

public View getFooterView(int position, View convertView,
        ViewGroup parent) {

        // the ListView has reached the last row
        TextView tvLastRow = new TextView(activity);
        if(AsyncHelper.isDownloadingImages){
            tvLastRow.setHint("Requesting new Images..");
        } else {

            tvLastRow.setHint("Reached the last row.");
        }
        tvLastRow.setGravity(Gravity.CENTER);
        return tvLastRow;

}

private OnClickListener myHotButtonClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        int position = (Integer) v.getTag();
        if(ActivityMain.user.isLoggedIn()){
            data.get(position).setThisUserVote(1);
            helper.vote_image(position, data.get(position).getId(), HOT);
        } else {
            Toast.makeText(activity, "Login to vote" , Toast.LENGTH_SHORT).show();
        }
    }
};

private OnClickListener myColdButtonClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        int position = (Integer) v.getTag();
        if(ActivityMain.user.isLoggedIn()){
            data.get(position).setThisUserVote(2);
            helper.vote_image(position, data.get(position).getId(), COLD);
        }else {
            Toast.makeText(activity, "Login to vote" , Toast.LENGTH_SHORT).show();
        }
    }
};

private OnClickListener myOptionsButtonClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        final int position = (Integer) v.getTag();
        Runnable optionsRunnable = new Runnable() {

            @Override
            public void run() {


                openOptionsDialog(position);

            }
        };
        handler.postDelayed(optionsRunnable, 500);


    }
};
private void openOptionsDialog(final int imgposition){
    final CharSequence[] items = {"Share", "Save", "Report"};

    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setTitle("Options");
    builder.setItems(items, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int item) {
            if(item==0){
                Utils.shareImage(activity, imageLoader.getImage(URL_FOLDER_IMAGES + data.get(imgposition).getUrl()) , data.get(imgposition).getTitle());
            } else if(item==1) {
                Utils.saveImage(imageLoader.getImage(URL_FOLDER_IMAGES + data.get(imgposition).getUrl()),activity);
            } else if(item==2) {
                openReportDialog(imgposition);
            }
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

private void openReportDialog(final int imgposition){

    AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style.AppCompatAlertDialogStyle);
    builder.setTitle("Report This Image?");
    builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            helper.reportImage(data.get(imgposition).getId());
        }
    });
    builder.setNegativeButton("No", null);

    AlertDialog alert = builder.create();
    alert.show();
}

public View getView(final int position, View convertView, ViewGroup parent) {
    if (getItemViewType(position) == VIEW_TYPE_LOADING) {
        // display the last row
        return getFooterView(position, convertView, parent);
    }
    View vi=convertView;
    final ViewHolder holder;
    final Image img = data.get(position);
    boolean isViNull = false;
    if(convertView==null){
    vi = inflater.inflate(R.layout.item_new_posts, null);
        holder = new ViewHolder();
        isViNull = true;
        holder.title=(BrushTextView)vi.findViewById(R.id.tv_newposts_title);
        holder.image=(RatioImageView)vi.findViewById(R.id.iv_newposts_image);
        holder.uploader = (BrushTextView) vi.findViewById(R.id.tv_newposts_uploader);
        holder.upvotes = (BrushTextView) vi.findViewById(R.id.tv_newposts_upvotes);
        holder.downvotes= (BrushTextView) vi.findViewById(R.id.tv_newposts_downvotes);
        holder.options=(LinearLayout)vi.findViewById(R.id.ll_newposts_button_options);

        holder.iv_hot=(ImageView)vi.findViewById(R.id.iv_newposts_button_upvote);
        holder.iv_cold=(ImageView)vi.findViewById(R.id.iv_newposts_button_downvote);
        holder.ll_hot=(LinearLayout)vi.findViewById(R.id.ll_newposts_button_upvote);
        holder.ll_cold=(LinearLayout)vi.findViewById(R.id.ll_newposts_button_downvote);

        vi.setTag(holder);

    } else {
        holder = (ViewHolder) vi.getTag();
    }


    if(img.getHeight() != 0 && img.getWidth() != 0){

        holder.image.getLayoutParams().height = img.getHeight();
        holder.image.getLayoutParams().width = img.getWidth();
        holder.image.requestLayout();
    }
    holder.ll_hot.setTag(position);
    holder.ll_hot.setOnClickListener(myHotButtonClickListener);
    holder.ll_cold.setTag(position);
    holder.ll_cold.setOnClickListener(myColdButtonClickListener);


    holder.options.setTag(position);
    holder.options.setOnClickListener(myOptionsButtonClickListener);


    changeVoteButtonImages(img, holder.iv_hot, holder.iv_cold);
    if(img.getTitle()!=null){
        holder.title.setVisibility(View.VISIBLE);
        holder.title.setText(img.getTitle());
    } else {
        holder.title.setVisibility(View.GONE);
    }
    holder.uploader.setText(img.getUploader());
    holder.upvotes.setText(img.getVotesUp()+"");
    holder.downvotes.setText(img.getVotesDown()+"");
    String url = URL_FOLDER_IMAGES + img.getUrl();
    System.out.println("GETVIEW NEW POST ADAPTER: height = " + img.getHeight() + "  width = " + img.getWidth());
    if(isViNull)
    System.out.println("GETVIEW CONVERTVIEW: VI: "  +vi.getHeight());
    imageLoader.DisplayImage(url, holder.image);

    return vi;
}

private void changeVoteButtonImages(Image image, ImageView upvote,ImageView  downvote){
    switch(image.getThisUserVote()){
    case 0:
        upvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_hot_0));
        downvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_cold_0));
        break;
    case 1:
        downvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_cold_0));
        upvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_hot_1));
        break;
    case 2:
        upvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_hot_0));
        downvote.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_post_cold_1));
        break;
    }
}

static class ViewHolder {            
   public BrushTextView title, uploader, upvotes, downvotes;
   public ImageView iv_hot,iv_cold;
   public LinearLayout options, ll_hot,ll_cold;
   public RatioImageView image; 
}

}

And here is the Fragment, which contains the ListView

public class Fragment_New_Posts extends Fragment implements Constants, OnRefreshListener{

private static final String ARG_SECTION_NUMBER = "section_number";

private ListView list;
private LazyNewPostsAdapter adapter;
private Images images;
private ArrayList<Image> imagesList;
private SharedPreferences prefs;
private Editor editor;
private int visible_i_id;
private SwipeRefreshLayout swipeLayout;
private int option_image_filter;
private AsyncHelper helper;
private boolean onRefreshFired = false;
private Parcelable state;

public static Fragment_New_Posts newInstance(int sectionNumber) {
    Fragment_New_Posts fragment = new Fragment_New_Posts();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

public static Fragment_New_Posts newInstance(int sectionNumber, Images imgs) {
    Fragment_New_Posts fragment = new Fragment_New_Posts(imgs);
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

public void updateImages(Images images, boolean createNew, boolean loadOldImages){
    int i_id_position = 0;
    this.images = images;
    if(!images.hasErrorOccured){
        if(this.imagesList == null || createNew || onRefreshFired){
            this.imagesList = images.getListOfImages();
        } else {
            this.imagesList.addAll(images.getListOfImages());
        }
    } 

    if(loadOldImages){
        i_id_position = this.images.getIDPosition(visible_i_id);
    }
    if(onRefreshFired){
        swipeLayout.setRefreshing(false);
        onRefreshFired = false;
    }
    synchronized (adapter) {
        adapter.updateData(this.imagesList);
        if(list!=null && createNew){
            if(loadOldImages){
                list.setSelection(i_id_position);
            } else {
                list.setSelection(0);
            }
        }
    }

}

private Handler handler = new Handler(){
    public void handleMessage(android.os.Message msg) {
        switch(msg.what){
        case HANDLER_MAIN_IMAGE_UPDATE:
            String imagesString =  (String) msg.obj;
            Images imgs = new Images(imagesString);
            updateImages(imgs, false, false);
            if(imgs.hasErrorOccured){
                Toast.makeText(getActivity(), "Can\'t get new Images", Toast.LENGTH_SHORT).show();
            }
            break;
        case HANDLER_IMAGE_SIZE_AVAILABLE:
            String url = (String) msg.obj;
            int height = msg.arg1;
            int width = msg.arg2;

            int imgPosition = findImageOfCertainURL(url);
            System.out.println("GETVIEW HANDLER 2: IMAGE POSITION" + imgPosition);
            if(imgPosition != -1){
                imagesList.get(imgPosition).setHeight(height);
                imagesList.get(imgPosition).setWidth(width);
            }

            break;
        }

    };
};

private int findImageOfCertainURL(String url){
    for(int i = 0; i <imagesList.size();i++){
        if((URL_FOLDER_IMAGES + imagesList.get(i).getUrl()).equalsIgnoreCase(url)){
            return i;
        }
    }
    return -1;
}

public Fragment_New_Posts() {
}

public Fragment_New_Posts(Images imgs) {
    this.images = imgs;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    System.out.println("NEW POST FRAGMENT ONCREATE");
    View rootView = inflater.inflate(R.layout.fragment_new_posts, container, false);
    prefs = getActivity().getSharedPreferences(PREF_WOODU, getActivity().MODE_PRIVATE);
    editor = prefs.edit();
    if(prefs!=null){
        visible_i_id = prefs.getInt(PREF_NEW_POSTS_VISIBLE_I_ID, 0);
        option_image_filter = prefs.getInt(PHP_TAG_IMAGE_FILTER, 0);
    }
    swipeLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
    swipeLayout.setColorSchemeColors(R.color.red_hot);
    swipeLayout.setOnRefreshListener(this);
    helper = new AsyncHelper(getActivity(), handler);
    imagesList = new ArrayList<Image>();
    if(images != null){
        imagesList = images.getListOfImages();
        System.out.println("SAVE IMAGES: load: imgsList " + imagesList);

    }
    list = (ListView) rootView.findViewById(R.id.lv_new_posts);
    adapter = new LazyNewPostsAdapter(getActivity(), imagesList, handler);
    list.setAdapter(adapter);

    list.setOnScrollListener(new EndlessScrollListener() {
        @Override
        public void onLoadMore(int page, int totalItemsCount) {
            if(imagesList!=null && imagesList.size()!=0){
                helper.getImageUpdate(imagesList.get(imagesList.size()-1).getId(), option_image_filter);
            }
        }
    });

    if(images != null){
        updateImages(images, true, true);
    }

    return rootView;
}



@Override
public void onPause() {
    int lastVisposition = list.getLastVisiblePosition();
    if(lastVisposition>=0 && lastVisposition < this.imagesList.size()){
        visible_i_id = this.imagesList.get(list.getFirstVisiblePosition()).getId();
        editor.putInt(PREF_NEW_POSTS_VISIBLE_I_ID, visible_i_id);
        editor.commit();
    }

    super.onPause();
}




@Override
public void onResume() {
    super.onResume();


}

@Override
public void onDestroy() {
    if(images != null){
        editor.putString(PREF_NEW_POSTS_CURRENT_IMAGES, Utils.createJSONStringFromImageArrayList(imagesList, editor));
        editor.commit();
    }
    super.onDestroy();
}

@Override
public void onRefresh() {
    onRefreshFired = true;
    if(prefs!=null){
        option_image_filter = prefs.getInt(PHP_TAG_IMAGE_FILTER, 0);
    }
    helper.getImageUpdate(0, option_image_filter);
}
}

Now here are many many information and code. I hope that does not scare anyone to help :D

Thanks!!

like image 465
Wicked161089 Avatar asked May 19 '15 17:05

Wicked161089


People also ask

How to move selected items up and down in listview?

The following code snippet demonstrate how to do that. The SwapLVItems function swap between 2 items (iItem1 and iItem2 are the index of the items in the ListView). The MoveLVSelectedItemsUp and MoveLVSelectedItemsDown functions move the selected items up and down.

How to scroll to random items in a listview?

In case the heights of the items are different and not set, move on to another method in this article. This example app contains a ListView with 100 items and a floating button. When the user presses the floating button, the view will scroll to a random item (you can replace it with a constant number if you want to).

How to move a list item from one index to another?

When you select a List Item click on Move Down. That time get the Current Index of the Selected List Item. Then remove the item from the Selected Index. And add the same Item object by Insert with Previous Selected Index + 1. For move up, subtract it by 1 i.e. previous selected index - 1.


1 Answers

Please, Please , Please don't "re-invent the Wheel" and use any lib out there for image loading, caching etc like Picasso, Fresco , Glide etc....

like image 169
murielK Avatar answered Oct 06 '22 13:10

murielK