My Application is a Launcher, I have probleme to get the good size of icon, i tried to use the list of icon and to set the right size. but with devices that have an xxhdpi, my application carsh. the Class used to get Application information
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Formatter.BigDecimalLayoutForm;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Adapter used for providing the applications to show on the launcher's basic
* view.
*
*/
public class GridViewAppInfoAdapter extends BaseAdapter {
private Rect mOldBounds = new Rect();
private List<ApplicationInfo> apps;
private Context context;
private static final String TAG = "GridViewAppInfoAdapter";
private static int lowVal;
private static int medVal;
private static int highVal;
private static int xhighVal;
private static int xxhighVal;
public static ArrayList<String> lApplication = new ArrayList<String>();
public static ArrayList<String> AppList = new ArrayList<String>();
public GridViewAppInfoAdapter(Context context, List<ApplicationInfo> apps) {
super();
this.context = context;
this.apps = apps;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Log.e("GridView", "getView");
final ApplicationInfo info = apps.get(position);
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.grid_item, parent, false);
}
Drawable icon = info.icon;
ImageView imageView = new ImageView(context);
if (!info.filtered) {
final Resources resources = context.getResources();
DisplayMetrics highmetrics = new DisplayMetrics();
highmetrics = resources.getDisplayMetrics();
int width = (int) resources
.getDimension(android.R.dimen.app_icon_size);
int height = (int) resources
.getDimension(android.R.dimen.app_icon_size);
final int iconWidth = icon.getIntrinsicWidth();
final int iconHeight = icon.getIntrinsicHeight();
if (icon instanceof PaintDrawable) {
PaintDrawable painter = (PaintDrawable) icon;
painter.setIntrinsicWidth(width);
painter.setIntrinsicHeight(height);
}
// if (width > 0 && height > 0
// && (width < iconWidth || height < iconHeight))
if (width > 0 && height > 0) {
final float ratio = (float) iconWidth / iconHeight;
if (iconWidth > iconHeight) {
height = (int) (width / ratio);
} else if (iconHeight > iconWidth) {
width = (int) (height * ratio);
}
if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
lowVal = 65;
medVal = 90;
highaVal = 130;
xhighVal = 180;
xxhighVal = 280;
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
lowVal = 36;
medVal = 48;
highVal = 72;
xhighVal = 96;
xxhighVal = 144;
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
lowVal = 36;
medVal = 48;
highVal = 130;
xhighVal = 173;
xxhighVal = 600;
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
}
switch (highmetrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
imageView.setLayoutParams(new GridView.LayoutParams(lowVal,
lowVal));
height = lowVal;
width = lowVal;
break;
case DisplayMetrics.DENSITY_MEDIUM:
imageView.setLayoutParams(new GridView.LayoutParams(medVal,
medVal));
height = medVal;
width = medVal;
break;
case DisplayMetrics.DENSITY_HIGH:
imageView.setLayoutParams(new GridView.LayoutParams(
highVal, highVal));
height = highVal;
width = highVal;
break;
case DisplayMetrics.DENSITY_XHIGH:
imageView.setLayoutParams(new GridView.LayoutParams(
xhighVal, xhighVal));
height = xhighVal;
width = xhighVal;
break;
case DisplayMetrics.DENSITY_XXHIGH:
imageView.setLayoutParams(new GridView.LayoutParams(
xxhighVal, xxhighVal));
height = xxhighVal;
width = xxhighVal;
break;
default:
break;
}
// System.gc();
final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap thumb;
try {
thumb = Bitmap.createBitmap(width, height, c);
} catch (Error e) {
thumb = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_4444);
}
final Canvas canvas = new Canvas(thumb);
canvas.setDrawFilter(new PaintFlagsDrawFilter(
Paint.DITHER_FLAG, 0));
// Copy the old bounds to restore them later
// If we were to do oldBounds = icon.getBounds(),
// the call to setBounds() that follows would
// change the same instance and we would lose the
// old bounds
mOldBounds.set(icon.getBounds());
icon.setBounds(
context.getResources().getInteger(
R.integer.image_padding),
context.getResources().getInteger(
R.integer.image_padding), width, height);
icon.draw(canvas);
icon.setBounds(mOldBounds);
icon = info.icon = new BitmapDrawable(thumb);
info.filtered = true;
}
}
final TextView textView = (TextView) convertView
.findViewById(R.id.label);
textView.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
textView.setText(info.title);
textView.setLines(2);
lApplication.add((info.title).toString());
return convertView;
}
#Override
public int getCount() {
// supprime les répétitions
List apps2 = new ArrayList();
Set set = new HashSet();
for (Object item : apps) {
if (!set.contains(item)) {
apps2.add(item);
set.add(item);
}
}
// Log.e("apps", "/" + set.size());
return set.size();
}
#Override
public Object getItem(int position) {
return apps.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setApps(List<ApplicationInfo> apps) {
this.apps = apps;
for (int i = 0; i < apps.size(); i++) {
AppList.add(apps.get(i).title.toString());
}
notifyDataSetChanged();
}
public ArrayList<String> getApplicationList() {
ArrayList<String> AppList = new ArrayList<String>();
for (int i = 0; i < apps.size(); i++) {
AppList.add(apps.get(i).title.toString());
}
return AppList;
}
}
I have a probleme of memory with XXHDPI the log is given below
4
: E/AndroidRuntime(11857): FATAL EXCEPTION: main
07-15 18:32:40.124: E/AndroidRuntime(11857): java.lang.OutOfMemoryError
07-15 18:32:40.124: E/AndroidRuntime(11857): at android.graphics.Bitmap.nativeCreate(Native Method)
07-15 18:32:40.124: E/AndroidRuntime(11857): at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
07-15 18:32:40.124: E/AndroidRuntime(11857): a
I don't know what to do.
Please recycle your Bitmaps, use the following link. It will stop your application from getting crashed.
http://developer.android.com/training/displaying-bitmaps/index.html
Replace
thumb = Bitmap.createBitmap(width, height, c);
to
thumb = Bitmap.createScaledBitmap(yourSelectedImage, h, w, true);
and check.
Related
I have already implemented Carousel Viewpager ...but I m stuck at one point.
There is 10 image item in ArrayList ...First 3 item (0,1,2 position) are showing and we can scroll horizontally one by one
What I want, When I click on first position i.e, 0 it should go position 1 and when I click on position 2, it should come position 1.
How can I achieve this?enter image description here
Method in mainActivity
private void showDrinkList() {
try {
DisplayMetrics metrics = new DisplayMetrics();
Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
int pageMargin = ((metrics.widthPixels / 3) * 2);
pager.setPageMargin(-pageMargin);
CarouselPagerAdapter adapter = new CarouselPagerAdapter(context,this.getChildFragmentManager(), this.getChildFragmentManager(), pager, drinkLists);
pager.setAdapter(adapter);
pager.addOnPageChangeListener(adapter);
if (drinkLists.size() > 1)
pager.setCurrentItem(1);
pager.setOffscreenPageLimit(3);
pager.setHorizontalScrollBarEnabled(true);
} catch (Exception e) {
e.printStackTrace();
} }
Carousel Adapter -
import android.content.Context;
import android.graphics.Interpolator;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.util.List;
import ae.frink.android.R;
import ae.frink.android.app.customDialog.RedeemDialog;
import ae.frink.android.model.BeanDrinkImage;
import ae.frink.android.utils.FixedSpeedScroller;
import ae.frink.android.utils.ViewPagerCustomDuration;
public class CarouselPagerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener {
public final static float BIG_SCALE = 0.8f;
private final static float SMALL_SCALE = 0.4f;
private final static float DIFF_SCALE = BIG_SCALE - SMALL_SCALE;
private FragmentManager context;
private Context c;
private FragmentManager fragmentManager;
private float scale;
public static ViewPager viewPager;
private List<BeanDrinkImage.DrinkList> drinkLists;
private CarouselPagerAdapter adapter;
//private ItemFragment itemFragment;
public CarouselPagerAdapter(Context c, FragmentManager context, FragmentManager fm, ViewPager viewPager,
List<BeanDrinkImage.DrinkList> drinkLists) {
super(fm);
this.fragmentManager = fm;
this.context = context;
this.c = c;
// this.itemFragment = new ItemFragment(drinkLists);
this.viewPager = viewPager;
this.drinkLists = drinkLists;}
#Override
public Fragment getItem(int position) {
// make the first pager bigger than others
try {
if (position == 0) //BarInformationFrag.FIRST_PAGE)
scale = SMALL_SCALE;
else if(position == 1)
scale = BIG_SCALE;
else if(position == 2)
scale = SMALL_SCALE;
else
scale = SMALL_SCALE;
position = position % drinkLists.size();
} catch (Exception e) {
e.printStackTrace();
}
Log.e("drinkSize", "....----" + drinkLists.size());
// ItemFragment itemFragment = new ItemFragment();
return ItemFragment.newInstance(context, position, scale, drinkLists);
}
#Override
public int getCount() {
// int count = 0;
// try {
// count = BarInformationFrag.count * BarInformationFrag.LOOPS;
// } catch (Exception e) {
// // TODO: handle exception
// e.printStackTrace();
// }
// return count;
return drinkLists.size();
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
try {
if (positionOffset >= 0f && positionOffset <= 1f) {
CarouselLinearLayout cur = getRootView(position);
CarouselLinearLayout next = getRootView(position + 1);
cur.setScaleBoth(BIG_SCALE - DIFF_SCALE * positionOffset);
next.setScaleBoth(SMALL_SCALE + DIFF_SCALE * positionOffset);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
#SuppressWarnings("ConstantConditions")
private CarouselLinearLayout getRootView(int position) {
return (CarouselLinearLayout) fragmentManager.findFragmentByTag(this.getFragmentTag(position))
.getView().findViewById(R.id.root_container);
}
private String getFragmentTag(int position) {
return "android:switcher:" + viewPager.getId() + ":" + position;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Carousel Linear Layout -
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.LinearLayout;
public class CarouselLinearLayout extends LinearLayout {
private float scale = CarouselPagerAdapter.BIG_SCALE;
// private float scale = .5f;
public CarouselLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CarouselLinearLayout(Context context) {
super(context);
}
public void setScaleBoth(float scale) {
this.scale = scale;
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// The main mechanism to display scale animation, you can customize it as your needs
int w = this.getWidth();
int h = this.getHeight();
canvas.scale(scale, scale, w / 2, h / 2);
}
}
item Fragment -
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import ae.frink.android.R;
import ae.frink.android.app.customDialog.RedeemDialog;
import ae.frink.android.connection.ApiClient;
import ae.frink.android.model.BeanDrinkImage;
import static ae.frink.android.Carousel.CarouselPagerAdapter.viewPager;
public class ItemFragment extends Fragment {
private static final String POSITON = "position";
private static final String SCALE = "scale";
private static final String DRAWABLE_RESOURE = "resource";
private static final String DRINK_LIST = "drinkList";
private List<BeanDrinkImage.DrinkList> dL;
private static final String IMAGE = "image";
public ArrayList<Integer> imageArray;
private Context context;
private List<BeanDrinkImage.DrinkList> drinkLists;
private SharedPreferences sharedPreferences;
private int screenWidth;
private int screenHeight;
/* private int[] imageArray = new int[]{R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1,
R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1,
R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1,
R.drawable.cocktail_lime_gin_fizz_1, R.drawable.cocktail_lime_gin_fizz_1};
*/
public ItemFragment() {
}
/*
#SuppressLint("ValidFragment")
public ItemFragment(List<BeanDrinkImage.DrinkList> drinkLists) {
this.drinkLists = drinkLists;
}
*/
public static Fragment newInstance(FragmentManager context, int pos, float scale, List<BeanDrinkImage.DrinkList> dL) {
ItemFragment fr = new ItemFragment();
Bundle b = new Bundle();
b.putInt(POSITON, pos);
b.putFloat(SCALE, scale);
b.putParcelableArrayList(DRINK_LIST, (ArrayList) dL);
//drinkLists=dL;
// this.context = context;
// this.dL = dL;
// b.putIntegerArrayList(IMAGE, imageArray);
Log.e("drinkSize", "....+++"+dL.size());
fr.setArguments(b);
return fr;//frFragment.instantiate(context, ItemFragment.class.getName(), b);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWidthAndHeight();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
#SuppressLint("SetTextI18n")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
context = getActivity();
final int postion = this.getArguments().getInt(POSITON);
float scale = this.getArguments().getFloat(SCALE);
this.imageArray = this.getArguments().getIntegerArrayList(IMAGE);
drinkLists = (ArrayList) this.getArguments().getParcelableArrayList(DRINK_LIST);
// TODO 21 sep changes
// LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(screenWidth / 3,
// h/4);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(screenWidth / 2,
screenWidth/2);
LinearLayout linearLayout = (LinearLayout) inflater.inflate(R.layout.fragment_image, container, false);
TextView textView = (TextView) linearLayout.findViewById(R.id.text);
CarouselLinearLayout root = (CarouselLinearLayout) linearLayout.findViewById(R.id.root_container);
ImageView imageView = (ImageView) linearLayout.findViewById(R.id.pagerImg);
ImageView starImage = (ImageView) linearLayout.findViewById(R.id.imgStar);
imageView.setLayoutParams(layoutParams);
String imageUrl = "";
try {
Log.e("drinkSize", "...."+drinkLists.size());
if (drinkLists.size() > 0) {
imageUrl = ApiClient.IMAGE_URL + drinkLists.get(postion).getImage();
Picasso.get().load(imageUrl).into(imageView);
Log.e("drinkName", drinkLists.get(postion).getDrinkName());
textView.setText(drinkLists.get(postion).getDrinkName());
if (drinkLists.get(postion).getIs_recomended() == 1) {
starImage.setVisibility(View.VISIBLE);
} else {
starImage.setVisibility(View.INVISIBLE);
}
}
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getActivity() != null) {
RedeemDialog redeemDialog = new RedeemDialog(getActivity(), drinkLists, postion);
redeemDialog.setCanceledOnTouchOutside(true);
redeemDialog.show();
// 12-march
/* if (sharedPreferences.getString(CommonVar.IS_SUBSCRIBED, "0").equals("0")) {
Toast.makeText(getContext(), "Please subscribe first", Toast.LENGTH_SHORT).show();
} else {
RedeemDialog redeemDialog = new RedeemDialog(getActivity(), list, postion);
redeemDialog.setCanceledOnTouchOutside(true);
redeemDialog.show();
}*/
}
}
});
root.setScaleBoth(scale);
} catch (Exception e) {
e.printStackTrace();
}
return linearLayout;
}
/**
* Get device screen width and height
*/
private void getWidthAndHeight() {
DisplayMetrics displaymetrics = new DisplayMetrics();
try {
Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHeight = displaymetrics.heightPixels;
screenWidth = displaymetrics.widthPixels;
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (position == 0) {
scale = SMALL_SCALE;}
else if(position == 1){
scale = BIG_SCALE;
}
else if(position == 2)
{
scale = SMALL_SCALE;
}
else{
scale = SMALL_SCALE;
}
holder.setIsRecyclable(false);
I read the sourec code RangeSeekBar.java in https://github.com/anothem/android-range-seek-bar/tree/master/rangeseekbar
Normally, in order to use string resource file, we should "import info.dao.myapp.R;"
But in the RangeSeekBar.java, I can't find any resource file import , but the class can use R.string.demo_min_label, why?
package org.florescu.android.rangeseekbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ImageView;
import org.florescu.android.util.BitmapUtil;
import org.florescu.android.util.PixelUtil;
import java.math.BigDecimal;
*/
public class RangeSeekBar<T extends Number> extends ImageView {
/**
* Default color of a {#link RangeSeekBar}, #FF33B5E5. This is also known as "Ice Cream Sandwich" blue.
*/
public static final int ACTIVE_COLOR = Color.argb(0xFF, 0x33, 0xB5, 0xE5);
/**
* An invalid pointer id.
*/
public static final int INVALID_POINTER_ID = 255;
// Localized constants from MotionEvent for compatibility
// with API < 8 "Froyo".
public static final int ACTION_POINTER_INDEX_MASK = 0x0000ff00, ACTION_POINTER_INDEX_SHIFT = 8;
public static final Integer DEFAULT_MINIMUM = 0;
public static final Integer DEFAULT_MAXIMUM = 100;
public static final int HEIGHT_IN_DP = 30;
public static final int TEXT_LATERAL_PADDING_IN_DP = 3;
private static final int INITIAL_PADDING_IN_DP = 8;
private static final int DEFAULT_TEXT_SIZE_IN_DP = 14;
private static final int DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP = 8;
private static final int DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP = 8;
private static final int LINE_HEIGHT_IN_DP = 1;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint shadowPaint = new Paint();
private Bitmap thumbImage;
private Bitmap thumbPressedImage;
private Bitmap thumbDisabledImage;
private float mThumbHalfWidth;
private float mThumbHalfHeight;
private float padding;
private T absoluteMinValue, absoluteMaxValue;
private NumberType numberType;
private double absoluteMinValuePrim, absoluteMaxValuePrim;
private double normalizedMinValue = 0d;
private double normalizedMaxValue = 1d;
private Thumb pressedThumb = null;
private boolean notifyWhileDragging = false;
private OnRangeSeekBarChangeListener<T> listener;
private float mDownMotionX;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaledTouchSlop;
private boolean mIsDragging;
private int mTextOffset;
private int mTextSize;
private int mDistanceToTop;
private RectF mRect;
private boolean mSingleThumb;
private boolean mAlwaysActive;
private boolean mShowLabels;
private boolean mShowTextAboveThumbs;
private float mInternalPad;
private int mActiveColor;
private int mDefaultColor;
private int mTextAboveThumbsColor;
private boolean mThumbShadow;
private int mThumbShadowXOffset;
private int mThumbShadowYOffset;
private int mThumbShadowBlur;
private Path mThumbShadowPath;
private Path mTranslatedThumbShadowPath = new Path();
private Matrix mThumbShadowMatrix = new Matrix();
private boolean mActivateOnDefaultValues;
public RangeSeekBar(Context context) {
super(context);
init(context, null);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RangeSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
#SuppressWarnings("unchecked")
private T extractNumericValueFromAttributes(TypedArray a, int attribute, int defaultValue) {
TypedValue tv = a.peekValue(attribute);
if (tv == null) {
return (T) Integer.valueOf(defaultValue);
}
int type = tv.type;
if (type == TypedValue.TYPE_FLOAT) {
return (T) Float.valueOf(a.getFloat(attribute, defaultValue));
} else {
return (T) Integer.valueOf(a.getInteger(attribute, defaultValue));
}
}
private void init(Context context, AttributeSet attrs) {
float barHeight;
int thumbNormal = R.drawable.seek_thumb_normal;
int thumbPressed = R.drawable.seek_thumb_pressed;
int thumbDisabled = R.drawable.seek_thumb_disabled;
int thumbShadowColor;
int defaultShadowColor = Color.argb(75, 0, 0, 0);
int defaultShadowYOffset = PixelUtil.dpToPx(context, 2);
int defaultShadowXOffset = PixelUtil.dpToPx(context, 0);
int defaultShadowBlur = PixelUtil.dpToPx(context, 2);
if (attrs == null) {
setRangeToDefaultValues();
mInternalPad = PixelUtil.dpToPx(context, INITIAL_PADDING_IN_DP);
barHeight = PixelUtil.dpToPx(context, LINE_HEIGHT_IN_DP);
mActiveColor = ACTIVE_COLOR;
mDefaultColor = Color.GRAY;
mAlwaysActive = false;
mShowTextAboveThumbs = true;
mTextAboveThumbsColor = Color.WHITE;
thumbShadowColor = defaultShadowColor;
mThumbShadowXOffset = defaultShadowXOffset;
mThumbShadowYOffset = defaultShadowYOffset;
mThumbShadowBlur = defaultShadowBlur;
mActivateOnDefaultValues = false;
} else {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar, 0, 0);
try {
setRangeValues(
extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMinValue, DEFAULT_MINIMUM),
extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMaxValue, DEFAULT_MAXIMUM)
);
mShowTextAboveThumbs = a.getBoolean(R.styleable.RangeSeekBar_valuesAboveThumbs, true);
mTextAboveThumbsColor = a.getColor(R.styleable.RangeSeekBar_textAboveThumbsColor, Color.WHITE);
mSingleThumb = a.getBoolean(R.styleable.RangeSeekBar_singleThumb, false);
mShowLabels = a.getBoolean(R.styleable.RangeSeekBar_showLabels, true);
mInternalPad = a.getDimensionPixelSize(R.styleable.RangeSeekBar_internalPadding, INITIAL_PADDING_IN_DP);
barHeight = a.getDimensionPixelSize(R.styleable.RangeSeekBar_barHeight, LINE_HEIGHT_IN_DP);
mActiveColor = a.getColor(R.styleable.RangeSeekBar_activeColor, ACTIVE_COLOR);
mDefaultColor = a.getColor(R.styleable.RangeSeekBar_defaultColor, Color.GRAY);
mAlwaysActive = a.getBoolean(R.styleable.RangeSeekBar_alwaysActive, false);
Drawable normalDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbNormal);
if (normalDrawable != null) {
thumbImage = BitmapUtil.drawableToBitmap(normalDrawable);
}
Drawable disabledDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbDisabled);
if (disabledDrawable != null) {
thumbDisabledImage = BitmapUtil.drawableToBitmap(disabledDrawable);
}
Drawable pressedDrawable = a.getDrawable(R.styleable.RangeSeekBar_thumbPressed);
if (pressedDrawable != null) {
thumbPressedImage = BitmapUtil.drawableToBitmap(pressedDrawable);
}
mThumbShadow = a.getBoolean(R.styleable.RangeSeekBar_thumbShadow, false);
thumbShadowColor = a.getColor(R.styleable.RangeSeekBar_thumbShadowColor, defaultShadowColor);
mThumbShadowXOffset = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowXOffset, defaultShadowXOffset);
mThumbShadowYOffset = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowYOffset, defaultShadowYOffset);
mThumbShadowBlur = a.getDimensionPixelSize(R.styleable.RangeSeekBar_thumbShadowBlur, defaultShadowBlur);
mActivateOnDefaultValues = a.getBoolean(R.styleable.RangeSeekBar_activateOnDefaultValues, false);
} finally {
a.recycle();
}
}
if (thumbImage == null) {
thumbImage = BitmapFactory.decodeResource(getResources(), thumbNormal);
}
if (thumbPressedImage == null) {
thumbPressedImage = BitmapFactory.decodeResource(getResources(), thumbPressed);
}
if (thumbDisabledImage == null) {
thumbDisabledImage = BitmapFactory.decodeResource(getResources(), thumbDisabled);
}
mThumbHalfWidth = 0.5f * thumbImage.getWidth();
mThumbHalfHeight = 0.5f * thumbImage.getHeight();
setValuePrimAndNumberType();
mTextSize = PixelUtil.dpToPx(context, DEFAULT_TEXT_SIZE_IN_DP);
mDistanceToTop = PixelUtil.dpToPx(context, DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP);
mTextOffset = !mShowTextAboveThumbs ? 0 : this.mTextSize + PixelUtil.dpToPx(context,
DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP) + this.mDistanceToTop;
mRect = new RectF(padding,
mTextOffset + mThumbHalfHeight - barHeight / 2,
getWidth() - padding,
mTextOffset + mThumbHalfHeight + barHeight / 2);
// make RangeSeekBar focusable. This solves focus handling issues in case EditText widgets are being used along with the RangeSeekBar within ScrollViews.
setFocusable(true);
setFocusableInTouchMode(true);
mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
if (mThumbShadow) {
// We need to remove hardware acceleration in order to blur the shadow
setLayerType(LAYER_TYPE_SOFTWARE, null);
shadowPaint.setColor(thumbShadowColor);
shadowPaint.setMaskFilter(new BlurMaskFilter(mThumbShadowBlur, BlurMaskFilter.Blur.NORMAL));
mThumbShadowPath = new Path();
mThumbShadowPath.addCircle(0,
0,
mThumbHalfHeight,
Path.Direction.CW);
}
}
#SuppressWarnings("unchecked")
// only used to set default values when initialised from XML without any values specified
private void setRangeToDefaultValues() {
this.absoluteMinValue = (T) DEFAULT_MINIMUM;
this.absoluteMaxValue = (T) DEFAULT_MAXIMUM;
setValuePrimAndNumberType();
}
private void setValuePrimAndNumberType() {
absoluteMinValuePrim = absoluteMinValue.doubleValue();
absoluteMaxValuePrim = absoluteMaxValue.doubleValue();
numberType = NumberType.fromNumber(absoluteMinValue);
}
/**
* Should the widget notify the listener callback while the user is still dragging a thumb? Default is false.
*/
#SuppressWarnings("unused")
public void setNotifyWhileDragging(boolean flag) {
this.notifyWhileDragging = flag;
}
/**
* Returns the currently selected min value.
*
* #return The currently selected min value.
*/
public T getSelectedMinValue() {
return normalizedToValue(normalizedMinValue);
}
/**
* Sets the currently selected minimum value. The widget will be invalidated and redrawn.
*
* #param value The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range.
*/
public void setSelectedMinValue(T value) {
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
setNormalizedMinValue(0d);
} else {
setNormalizedMinValue(valueToNormalized(value));
}
}
/**
* Returns the currently selected max value.
*
* #return The currently selected max value.
*/
public T getSelectedMaxValue() {
return normalizedToValue(normalizedMaxValue);
}
/**
* Sets the currently selected maximum value. The widget will be invalidated and redrawn.
*
* #param value The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range.
*/
public void setSelectedMaxValue(T value) {
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
setNormalizedMaxValue(1d);
} else {
setNormalizedMaxValue(valueToNormalized(value));
}
}
#SuppressWarnings("unused")
public void setOnRangeSeekBarChangeListener(OnRangeSeekBarChangeListener<T> listener) {
this.listener = listener;
}
#SuppressWarnings("unused")
public void setThumbShadowPath(Path thumbShadowPath) {
this.mThumbShadowPath = thumbShadowPath;
}
/**
* Draws the widget on the given canvas.
*/
#Override
protected synchronized void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
paint.setTextSize(mTextSize);
paint.setStyle(Style.FILL);
paint.setColor(mDefaultColor);
paint.setAntiAlias(true);
float minMaxLabelSize = 0;
if (mShowLabels) {
// draw min and max labels
String minLabel = getContext().getString(R.string.demo_min_label);
String maxLabel = getContext().getString(R.string.demo_max_label);
minMaxLabelSize = Math.max(paint.measureText(minLabel), paint.measureText(maxLabel));
float minMaxHeight = mTextOffset + mThumbHalfHeight + mTextSize / 3;
canvas.drawText(minLabel, 0, minMaxHeight, paint);
canvas.drawText(maxLabel, getWidth() - minMaxLabelSize, minMaxHeight, paint);
}
padding = mInternalPad + minMaxLabelSize + mThumbHalfWidth;
// draw seek bar background line
mRect.left = padding;
mRect.right = getWidth() - padding;
canvas.drawRect(mRect, paint);
boolean selectedValuesAreDefault = (getSelectedMinValue().equals(getAbsoluteMinValue()) &&
getSelectedMaxValue().equals(getAbsoluteMaxValue()));
int colorToUseForButtonsAndHighlightedLine = !mAlwaysActive && !mActivateOnDefaultValues && selectedValuesAreDefault ?
mDefaultColor : // default values
mActiveColor; // non default, filter is active
// draw seek bar active range line
mRect.left = normalizedToScreen(normalizedMinValue);
mRect.right = normalizedToScreen(normalizedMaxValue);
paint.setColor(colorToUseForButtonsAndHighlightedLine);
canvas.drawRect(mRect, paint);
// draw minimum thumb (& shadow if requested) if not a single thumb control
if (!mSingleThumb) {
if (mThumbShadow) {
drawThumbShadow(normalizedToScreen(normalizedMinValue), canvas);
}
drawThumb(normalizedToScreen(normalizedMinValue), Thumb.MIN.equals(pressedThumb), canvas,
selectedValuesAreDefault);
}
// draw maximum thumb & shadow (if necessary)
if (mThumbShadow) {
drawThumbShadow(normalizedToScreen(normalizedMaxValue), canvas);
}
drawThumb(normalizedToScreen(normalizedMaxValue), Thumb.MAX.equals(pressedThumb), canvas,
selectedValuesAreDefault);
// draw the text if sliders have moved from default edges
if (mShowTextAboveThumbs && (mActivateOnDefaultValues || !selectedValuesAreDefault)) {
paint.setTextSize(mTextSize);
paint.setColor(mTextAboveThumbsColor);
// give text a bit more space here so it doesn't get cut off
int offset = PixelUtil.dpToPx(getContext(), TEXT_LATERAL_PADDING_IN_DP);
String minText = String.valueOf(getSelectedMinValue());
String maxText = String.valueOf(getSelectedMaxValue());
float minTextWidth = paint.measureText(minText) + offset;
float maxTextWidth = paint.measureText(maxText) + offset;
if (!mSingleThumb) {
canvas.drawText(minText,
normalizedToScreen(normalizedMinValue) - minTextWidth * 0.5f,
mDistanceToTop + mTextSize,
paint);
}
canvas.drawText(maxText,
normalizedToScreen(normalizedMaxValue) - maxTextWidth * 0.5f,
mDistanceToTop + mTextSize,
paint);
}
}
}
But have you tried the git the project to your workspace and build it locally successful?
Below is my AppConstant.java
package com.domore.gridviewtutorial.helper;
import java.util.Arrays;
import java.util.List;
/**
* Created by MY WORLD on 11/28/2015.
*/
public class AppContant {
// Number of columns of Grid View
public static final int NUM_OF_COLUMNS = 3;
// Gridview image padding
public static final int GRID_PADDING = 8; // in dp
// SD card image directory
public static final String PHOTO_ALBUM = "MyPhotos";
// supported file formats
public static final List<String> FILE_EXTN = Arrays.asList("jpg", "jpeg",
"png");
}
in this class i set the file extension which i load in my app
Here, is my utils class
package com.domore.gridviewtutorial.helper;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Point;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
/**
* Created by MY WORLD on 11/28/2015.
*/
public class Utils {
private Context context;
public Utils(Context context){
this.context=context;
}
public ArrayList<String> getFilePaths(){
ArrayList<String> filePaths=new ArrayList<String>();
File directory=new File(android.os.Environment.getExternalStorageDirectory()+File.separator+AppContant.PHOTO_ALBUM);
if(directory.isDirectory()){
File[] listFiles=directory.listFiles();
if(listFiles.length > 0 ){
for(int i=0;i<listFiles.length;i++){
String filePath=listFiles[i].getAbsolutePath();
if(IsSupportedFile(filePath)){
filePaths.add(filePath);
}
}
}
else{
Toast.makeText(
context,
AppContant.PHOTO_ALBUM
+ " is empty. Please load some images in it !",
Toast.LENGTH_LONG).show();
}
}
else{
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Error!");
alert.setMessage(AppContant.PHOTO_ALBUM
+ " directory path is not valid! Please set the image directory name AppConstant.java class");
alert.setPositiveButton("OK", null);
alert.show();
}
return filePaths;
}
private boolean IsSupportedFile(String filePath) {
String ext = filePath.substring((filePath.lastIndexOf(".") + 1),
filePath.length());
if (AppContant.FILE_EXTN
.contains(ext.toLowerCase(Locale.getDefault())))
return true;
else
return false;
}
public int getScreenWidth() {
int columnWidth;
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
columnWidth = point.x;
return columnWidth;
}
}
Here is my grid_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:gravity="center"
android:stretchMode="columnWidth"
android:background="#000000">
</GridView>
i have Adapter class to load images
package com.domore.gridviewtutorial.adapter;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.GridView;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import android.view.View.OnClickListener;
/**
* Created by MY WORLD on 11/28/2015.
*/
public class GridViewImageAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<String> _filePaths=new ArrayList<String>();
private int imageWidth;
public GridViewImageAdapter(Activity activity,ArrayList<String> _filePaths,int imageWidth){
this.activity=activity;
this._filePaths=_filePaths;
this.imageWidth=imageWidth;
}
#Override
public int getCount() {
return this._filePaths.size();
}
#Override
public Object getItem(int position) {
return this._filePaths.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView==null){
imageView=new ImageView(this.activity);
}
else{
imageView=(ImageView)convertView;
}
Bitmap image=decodeFile(this._filePaths.get(position),imageWidth,imageWidth);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth,
imageWidth));
imageView.setImageBitmap(image);
// image view click listener
imageView.setOnClickListener(new OnImageClickListener(position));
return imageView;
}
class OnImageClickListener implements OnClickListener {
int _postion;
// constructor
public OnImageClickListener(int position) {
this._postion = position;
}
#Override
public void onClick(View v) {
// on selecting grid view image
// launch full screen activity
// Intent i = new Intent(activity, FullScreenViewActivity.class);
// i.putExtra("position", _postion);
// activity.startActivity(i);
}
}
/*
* Resizing image size
*/
public static Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
try {
File f = new File(filePath);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
Here is my MainActivity.java
package com.domore.gridviewtutorial;
import android.content.res.Resources;
import android.support.v7.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.GridLayoutAnimationController;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import com.domore.gridviewtutorial.adapter.GridViewImageAdapter;
import com.domore.gridviewtutorial.helper.AppContant;
import com.domore.gridviewtutorial.helper.Utils;
import java.util.ArrayList;
public class AndroidGridLayoutActivity extends AppCompatActivity {
private Utils utils;
private ArrayList<String> imagePaths = new ArrayList<String>();
private GridViewImageAdapter adapter;
private GridView gridView;
private int columnWidth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
GridView gridView=(GridView)findViewById(R.id.grid_view);
utils=new Utils(this);
InitilizeGridLayout();
imagePaths=utils.getFilePaths();
adapter=new GridViewImageAdapter(AndroidGridLayoutActivity.this,imagePaths,columnWidth);
gridView.setAdapter(adapter);
}
private void InitilizeGridLayout() {
Resources r = getResources();
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppContant.GRID_PADDING, r.getDisplayMetrics());
columnWidth = (int) ((utils.getScreenWidth() - ((AppContant.NUM_OF_COLUMNS + 1) * padding)) / AppContant.NUM_OF_COLUMNS);
gridView.setNumColumns(AppContant.NUM_OF_COLUMNS);
gridView.setColumnWidth(columnWidth);
gridView.setStretchMode(GridView.NO_STRETCH);
gridView.setPadding((int) padding, (int) padding, (int) padding,
(int) padding);
gridView.setHorizontalSpacing((int) padding);
gridView.setVerticalSpacing((int) padding);
}
}
I got error in mainActivity.java
here is my error
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setNumColumns(int)' on a null object reference
at com.domore.gridviewtutorial.AndroidGridLayoutActivity.InitilizeGridLayout(AndroidGridLayoutActivity.java:46)
at com.domore.gridviewtutorial.AndroidGridLayoutActivity.onCreate(AndroidGridLayoutActivity.java:34)
can anyone who help me to solve out this error i cannot able to understand.
Your gridView variable is null because you are recreating the a new variable gridView in your onCreate() method and your's activity's instance gridView variable is never get Initialized.
public class AndroidGridLayoutActivity extends AppCompatActivity {
private Utils utils;
private ArrayList<String> imagePaths = new ArrayList<String>();
private GridViewImageAdapter adapter;
private GridView gridView;
private int columnWidth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
// initiated the gridView variable
gridView=(GridView)findViewById(R.id.grid_view);
utils=new Utils(this);
InitilizeGridLayout();
imagePaths=utils.getFilePaths();
adapter=new GridViewImageAdapter(AndroidGridLayoutActivity.this,imagePaths,columnWidth);
gridView.setAdapter(adapter);
}
private void InitilizeGridLayout() {
Resources r = getResources();
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppContant.GRID_PADDING, r.getDisplayMetrics());
columnWidth = (int) ((utils.getScreenWidth() - ((AppContant.NUM_OF_COLUMNS + 1) * padding)) / AppContant.NUM_OF_COLUMNS);
gridView.setNumColumns(AppContant.NUM_OF_COLUMNS);
gridView.setColumnWidth(columnWidth);
gridView.setStretchMode(GridView.NO_STRETCH);
gridView.setPadding((int) padding, (int) padding, (int) padding,
(int) padding);
gridView.setHorizontalSpacing((int) padding);
gridView.setVerticalSpacing((int) padding);
}
}
I want to implement drag and drop of list-items in my application. I followed this, it works well for lists containing text only. I integrated lazy-list with images along with drag and drop. But, while I drag the item, the dragged item goes to actual position. The item below the dragged item gets removed from the list. After I take my fingers off, dragged item doesn't move to the place I wish. What is wrong with this code?
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.listviewdragginganimation.DynamicListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<Button
android:id="#+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Clear Cache"/>
</LinearLayout>
DynamicListView.Java:
package com.listviewdragginganimation;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import java.util.ArrayList;
public class DynamicListView extends ListView {
private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
private final int MOVE_DURATION = 150;
private final int LINE_THICKNESS = 15;
public ArrayList<String> mCheeseList;
private int mLastEventY = -1;
private int mDownY = -1;
private int mDownX = -1;
private int mTotalOffset = 0;
private boolean mCellIsMobile = false;
private boolean mIsMobileScrolling = false;
private int mSmoothScrollAmountAtEdge = 0;
private final int INVALID_ID = -1;
private long mAboveItemId = INVALID_ID;
private long mMobileItemId = INVALID_ID;
private long mBelowItemId = INVALID_ID;
private BitmapDrawable mHoverCell;
private Rect mHoverCellCurrentBounds;
private Rect mHoverCellOriginalBounds;
private final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private boolean mIsWaitingForScrollFinish = false;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
public DynamicListView(Context context) {
super(context);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context) {
setOnItemLongClickListener(mOnItemLongClickListener);
setOnScrollListener(mScrollListener);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mSmoothScrollAmountAtEdge = (int) (SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
}
private AdapterView.OnItemLongClickListener mOnItemLongClickListener = new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos,
long id) {
mTotalOffset = 0;
int position = pointToPosition(mDownX, mDownY);
int itemNum = position - getFirstVisiblePosition();
View selectedView = getChildAt(itemNum);
mMobileItemId = getAdapter().getItemId(position);
mHoverCell = getAndAddHoverView(selectedView);
selectedView.setVisibility(INVISIBLE);
mCellIsMobile = true;
updateNeighborViewsForID(mMobileItemId);
return true;
}
};
private BitmapDrawable getAndAddHoverView(View v) {
int w = v.getWidth();
int h = v.getHeight();
int top = v.getTop();
int left = v.getLeft();
Bitmap b = getBitmapWithBorder(v);
BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
drawable.setBounds(mHoverCellCurrentBounds);
return drawable;
}
/** Draws a black border over the screenshot of the view passed in. */
private Bitmap getBitmapWithBorder(View v) {
Bitmap bitmap = getBitmapFromView(v);
Canvas can = new Canvas(bitmap);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(LINE_THICKNESS);
paint.setColor(Color.BLACK);
can.drawBitmap(bitmap, 0, 0, null);
can.drawRect(rect, paint);
return bitmap;
}
/** Returns a bitmap showing a screenshot of the view passed in. */
private Bitmap getBitmapFromView(View v) {
Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
return bitmap;
}
private void updateNeighborViewsForID(long itemID) {
int position = getPositionForID(itemID);
LazyAdapter adapter = ((LazyAdapter) getAdapter());
mAboveItemId = adapter.getItemId(position - 1);
mBelowItemId = adapter.getItemId(position + 1);
}
/** Retrieves the view in the list corresponding to itemID */
public View getViewForID(long itemID) {
int firstVisiblePosition = getFirstVisiblePosition();
LazyAdapter adapter = ((LazyAdapter) getAdapter());
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
int position = firstVisiblePosition + i;
long id = adapter.getItemId(position);
if (id == itemID) {
return v;
}
}
return null;
}
/** Retrieves the position in the list corresponding to itemID */
public int getPositionForID(long itemID) {
View v = getViewForID(itemID);
if (v == null) {
return -1;
} else {
return getPositionForView(v);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHoverCell != null) {
mHoverCell.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX();
mDownY = (int) event.getY();
mActivePointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER_ID) {
break;
}
int pointerIndex = event.findPointerIndex(mActivePointerId);
mLastEventY = (int) event.getY(pointerIndex);
int deltaY = mLastEventY - mDownY;
if (mCellIsMobile) {
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
mHoverCell.setBounds(mHoverCellCurrentBounds);
invalidate();
// Log.v("handle switch 1","1");
handleCellSwitch();
// Log.v("handle switch 2","2");
mIsMobileScrolling = false;
handleMobileCellScroll();
return false;
}
break;
case MotionEvent.ACTION_UP:
touchEventsEnded();
break;
case MotionEvent.ACTION_CANCEL:
touchEventsCancelled();
break;
case MotionEvent.ACTION_POINTER_UP:
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
touchEventsEnded();
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void handleCellSwitch() {
final int deltaY = mLastEventY - mDownY;
int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
View belowView = getViewForID(mBelowItemId);
View mobileView = getViewForID(mMobileItemId);
View aboveView = getViewForID(mAboveItemId);
boolean isBelow = (belowView != null)
&& (deltaYTotal > belowView.getTop());
boolean isAbove = (aboveView != null)
&& (deltaYTotal < aboveView.getTop());
if (isBelow || isAbove) {
final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
View switchView = isBelow ? belowView : aboveView;
final int originalItem = getPositionForView(mobileView);
if (switchView == null) {
updateNeighborViewsForID(mMobileItemId);
return;
}
Log.v("swapElements switch 1", "1");
Log.v("swapElements originalItem 1", originalItem + "");
Log.v("swapElements switchView 1", "" + switchView);
setCheeseList(MainActivity.mCheeseList);
Log.v("mCheeseList item", mCheeseList.get(originalItem));
swapElements(mCheeseList, originalItem,
getPositionForView(switchView));
Log.v("swapElements switch 2", "2");
// ((BaseAdapter) getAdapter()).notifyDataSetChanged();
MainActivity.adapter.notifyDataSetChanged();
mDownY = mLastEventY;
final int switchViewStartTop = switchView.getTop();
mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
updateNeighborViewsForID(mMobileItemId);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
View switchView = getViewForID(switchItemID);
mTotalOffset += deltaY;
int switchViewNewTop = switchView.getTop();
int delta = switchViewStartTop - switchViewNewTop;
switchView.setTranslationY(delta);
ObjectAnimator animator = ObjectAnimator.ofFloat(
switchView, View.TRANSLATION_Y, 0);
animator.setDuration(MOVE_DURATION);
animator.start();
return true;
}
});
}
}
private void swapElements(ArrayList<String> arrayList, int indexOne,
int indexTwo) {
Log.v("index one", indexOne + "");
Log.v("index two", indexTwo + "");
Log.v("temp", arrayList.get(indexOne));
String temp = arrayList.get(indexOne);
arrayList.set(indexOne, arrayList.get(indexTwo));
arrayList.set(indexTwo, temp);
}
/**
* Resets all the appropriate fields to a default state while also animating
* the hover cell back to its correct location.
*/
private void touchEventsEnded() {
final View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile || mIsWaitingForScrollFinish) {
mCellIsMobile = false;
mIsWaitingForScrollFinish = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
// If the autoscroller has not completed scrolling, we need to wait
// for it to
// finish in order to determine the final location of where the
// hover cell
// should be animated to.
if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
mIsWaitingForScrollFinish = true;
return;
}
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
mobileView.getTop());
ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(
mHoverCell, "bounds", sBoundEvaluator,
mHoverCellCurrentBounds);
hoverViewAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(
ValueAnimator valueAnimator) {
invalidate();
}
});
hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
setEnabled(false);
}
#Override
public void onAnimationEnd(Animator animation) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
setEnabled(true);
invalidate();
}
});
hoverViewAnimator.start();
} else {
touchEventsCancelled();
}
}
/**
* Resets all the appropriate fields to a default state.
*/
private void touchEventsCancelled() {
View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
invalidate();
}
mCellIsMobile = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
}
/**
* This TypeEvaluator is used to animate the BitmapDrawable back to its
* final location when the user lifts his finger by modifying the
* BitmapDrawable's bounds.
*/
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
return new Rect(interpolate(startValue.left, endValue.left,
fraction), interpolate(startValue.top, endValue.top,
fraction), interpolate(startValue.right, endValue.right,
fraction), interpolate(startValue.bottom, endValue.bottom,
fraction));
}
public int interpolate(int start, int end, float fraction) {
return (int) (start + fraction * (end - start));
}
};
private void handleMobileCellScroll() {
mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
}
public boolean handleMobileCellScroll(Rect r) {
int offset = computeVerticalScrollOffset();
int height = getHeight();
int extent = computeVerticalScrollExtent();
int range = computeVerticalScrollRange();
int hoverViewTop = r.top;
int hoverHeight = r.height();
if (hoverViewTop <= 0 && offset > 0) {
smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
return true;
}
if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
return true;
}
return false;
}
public void setCheeseList(ArrayList<String> cheeseList) {
mCheeseList = cheeseList;
}
private AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener() {
private int mPreviousFirstVisibleItem = -1;
private int mPreviousVisibleItemCount = -1;
private int mCurrentFirstVisibleItem;
private int mCurrentVisibleItemCount;
private int mCurrentScrollState;
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mCurrentFirstVisibleItem = firstVisibleItem;
mCurrentVisibleItemCount = visibleItemCount;
mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
: mPreviousFirstVisibleItem;
mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
: mPreviousVisibleItemCount;
checkAndHandleFirstVisibleCellChange();
checkAndHandleLastVisibleCellChange();
mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
mPreviousVisibleItemCount = mCurrentVisibleItemCount;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
mScrollState = scrollState;
isScrollCompleted();
}
private void isScrollCompleted() {
if (mCurrentVisibleItemCount > 0
&& mCurrentScrollState == SCROLL_STATE_IDLE) {
if (mCellIsMobile && mIsMobileScrolling) {
handleMobileCellScroll();
} else if (mIsWaitingForScrollFinish) {
touchEventsEnded();
}
}
}
/**
* Determines if the listview scrolled up enough to reveal a new cell at
* the top of the list. If so, then the appropriate parameters are
* updated.
*/
public void checkAndHandleFirstVisibleCellChange() {
if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
/**
* Determines if the listview scrolled down enough to reveal a new cell
* at the bottom of the list. If so, then the appropriate parameters are
* updated.
*/
public void checkAndHandleLastVisibleCellChange() {
int currentLastVisibleItem = mCurrentFirstVisibleItem
+ mCurrentVisibleItemCount;
int previousLastVisibleItem = mPreviousFirstVisibleItem
+ mPreviousVisibleItemCount;
if (currentLastVisibleItem != previousLastVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
};
}
LazyAdapter.java:
package com.listviewdragginganimation;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<String> data=new ArrayList<String>();
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(MainActivity a, ArrayList<String> mCheeseList) {
// TODO Auto-generated constructor stub
activity = a;
data=mCheeseList;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.item, null);
TextView text=(TextView)vi.findViewById(R.id.text);;
ImageView image=(ImageView)vi.findViewById(R.id.image);
text.setText("item "+position);
imageLoader.DisplayImage(data.get(position), image);
return vi;
}
}
MainActivity.java:
package com.listviewdragginganimation;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
ListView list;
static LazyAdapter adapter;
static ArrayList<String>mCheeseList = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i = 0; i < mStrings.length; ++i) {
mCheeseList.add(mStrings[i]);
}
list=(ListView)findViewById(R.id.list);
adapter=new LazyAdapter(this, mCheeseList);
list.setAdapter(adapter);
Button b=(Button)findViewById(R.id.button1);
b.setOnClickListener(listener);
}
#Override
public void onDestroy()
{
list.setAdapter(null);
super.onDestroy();
}
public OnClickListener listener=new OnClickListener(){
#Override
public void onClick(View arg0) {
adapter.imageLoader.clearCache();
adapter.notifyDataSetChanged();
}
};
private String[] mStrings={
"http://a3.twimg.com/profile_images/670625317/aam-logo-v3-twitter.png",
"http://a3.twimg.com/profile_images/740897825/AndroidCast-350_normal.png",
"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",
"http://a1.twimg.com/profile_images/97470808/icon_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon.png",
"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
};
}
I found this particular code https://github.com/bauerca/drag-sort-listview in this url and in it I was able to add images also...
I'm also trying to make a custom layout. Added an image (from a 'drawable' folder) to 'layout/text_view.xml' (inserted in a LinearLayout). Changed StableArrayAdapter to extend BaseAdapter and rewrote getView (I think you can also make this with ArrayAdapter like https://stackoverflow.com/a/30270370/2914140). Then applied some changes for Lollipop from ListViewDraggingAnimation broken on Android 5 Lollipop and https://www.youtube.com/all_comments?v=_BZIvjMgH-Q. At least, static images are dragged along with text. When I change an ImageView to a WebVew, there are many errors and bugs.
Is there some way to implement drag and drop functionality in API 8 Android?
Looked here, but it appears after API 11.
I need to drag view from one LinearLayout to another. Ho can i implement this on API 8?
Try like this
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
ListView source = null;
TextView target1 = null;
TextView target2 = null;
TextView target3 = null;
String[] listItems = {"Samsung", "Apple", "Google", "Nokia"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
source = (ListView)findViewById(R.id.dragSource);
target1 = (TextView) findViewById(R.id.dragTarget1);
target2 = (TextView) findViewById(R.id.dragTarget2);
target3 = (TextView) findViewById(R.id.dragTarget3);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listItems);
source.setAdapter(adapter);
// Start Drag
source.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String item = listItems[position];
ClipData data = ClipData.newPlainText("DragIt", item);
source.startDrag(data, new MyShadowBuilder(view), null, 0);
}
});
// Handle Drag
target1.setOnDragListener(new MyDragListener());
target2.setOnDragListener(new MyDragListener());
target3.setOnDragListener(new MyDragListener());
}
// Drag Shadow
private class MyShadowBuilder extends DragShadowBuilder {
public MyShadowBuilder(View v) {
super(v);
}
#Override
public void onDrawShadow(Canvas canvas) {
// Set Drag image background or anything you want
int width = getView().getWidth();
int height = getView().getHeight();
Paint paint = new Paint();
paint.setColor(0x55858585);
canvas.drawRect(new Rect(0, 0, width, height), paint);
super.onDrawShadow(canvas);
}
#Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
int width = getView().getWidth();
int height = getView().getHeight();
shadowSize.set(width, height);
shadowTouchPoint.set(width/2, height);
}
}
// Drag Listener
private class MyDragListener implements OnDragListener {
private final int DEFAULT_BG_COLOR = 0xFF858585;
private final int HIGHLIGHT_BG_COLOR = 0xFF0000FF;
#Override
public boolean onDrag(View v, DragEvent event) {
if(event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
v.setBackgroundColor(HIGHLIGHT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DRAG_EXITED) {
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DROP) {
// Perform drop
ClipData clip = event.getClipData();
ClipData.Item item = clip.getItemAt(0);
String text = item.getText().toString();
((TextView) v).setText(text);
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
// Send true to listen All Drag Events.
return true;
}
}
}
XML is like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="161dp"
android:layout_height="fill_parent"
android:background="#FF858585"
android:orientation="vertical" >
<TextView
android:id="#+id/dragTarget1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/dragTarget2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/dragTarget3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/dragSource"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Try another approach by using WindowManager :
package com.example.cooldraganddrop;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`
private static final int ITEM_HOVER_DELAY = 450;
private int mDragPointX;
private int mDragPointY;
private int mDragOffsetX;
private int mDragOffsetY;
private int mDragPosition = AdapterView.INVALID_POSITION;
private int mDropPosition = AdapterView.INVALID_POSITION;
private int mCurrentPosition = AdapterView.INVALID_POSITION;
private Runnable mDelayedOnDragRunnable = null;
ScrollingStrategy mScrollingStrategy = null;
WindowManager mWindowManager = null;
WindowManager.LayoutParams mWindowParams = null;
private ImageView mDragImageView = null;
private boolean mDragAndDropStarted = false;
private DragAndDropListener mDragAndDropListener = null;
private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;
public static interface OnTrackTouchEventsListener {
void trackTouchEvents(final MotionEvent motionEvent);
};
public static interface DragAndDropListener {
void onDragItem(int from);
void onDraggingItem(int from, int to);
void onDropItem(int from, int to);
boolean isDragAndDropEnabled(int position);
}
public CoolDragAndDropGridView(Context context) {
super(context);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
private void initialize() {
setOnTouchListener(this);
setChildrenDrawingOrderEnabled(true);
}
public void startDragAndDrop() {
mDragAndDropStarted = true;
}
public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {
mDragAndDropListener = dragAndDropListener;
}
private void destroyDragImageView() {
if (mDragImageView != null) {
mWindowManager.removeView(mDragImageView);
BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
if (bitmapDrawable != null) {
final Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
mDragImageView.setImageDrawable(null);
mDragImageView = null;
}
}
private ImageView createDragImageView(final View v, final int x, final int y) {
v.destroyDrawingCache();
v.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());
mDragPointX = x - v.getLeft();
mDragPointY = y - v.getTop();
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.alpha = 0.7f;
mWindowParams.windowAnimations = 0;
ImageView iv = new ImageView(getContext());
iv.setBackgroundColor(Color.parseColor("#ff555555"));
iv.setImageBitmap(bm);
mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
mWindowManager.addView(iv, mWindowParams);
return iv;
}
private void startDrag(final int x, final int y) {
final View v = getChildAt(mDragPosition);
destroyDragImageView();
mDragImageView = createDragImageView(v, x, y);
v.setVisibility(View.INVISIBLE);
if (mDragAndDropListener != null) {
mDragAndDropListener.onDragItem(mDragPosition);
}
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if (mCurrentPosition == -1)
return i;
else if (i == childCount - 1)
return mCurrentPosition;
else if (i >= mCurrentPosition)
return i + 1;
return i;
}
private void onDrop() {
destroyDragImageView();
removeCallbacks(mDelayedOnDragRunnable);
View v = getChildAt(mDropPosition);
v.setVisibility(View.VISIBLE);
v.clearAnimation();
if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {
mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
}
mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
mDragAndDropStarted = false;
}
public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {
mScrollingStrategy = scrollingStrategy;
}
private void onDrag(final int x, final int y) {
if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {
removeCallbacks(mDelayedOnDragRunnable);
return;
}
final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);
if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {
removeCallbacks(mDelayedOnDragRunnable);
if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {
mDropPosition = tempDropPosition;
mDelayedOnDragRunnable = new Runnable() {
#Override
public void run() {
mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
performDragAndDropSwapping(mCurrentPosition, tempDropPosition);
final int nextDropPosition = pointToPosition(tempDropPosition, x, y);
if (nextDropPosition == AdapterView.INVALID_POSITION) {
mCurrentPosition = mDropPosition = tempDropPosition;
}
}
};
postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);
} else {
mDropPosition = mDragPosition;
}
}
if (mDragImageView != null) {
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
}
}
public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {
mOnTrackTouchEventsListener = onTrackTouchEventsListener;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mOnTrackTouchEventsListener != null) {
mOnTrackTouchEventsListener.trackTouchEvents(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (mDragAndDropListener != null && mDragAndDropStarted) {
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(true);
return launchDragAndDrop(event);
}
break;
default:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(event);
}
private boolean launchDragAndDrop(final MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);
if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
startDrag(x, y);
return true;
}
return false;
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {
final int x = (int) event.getX();
final int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
onDrag(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
onDrop();
resetLongClickTransition();
getParent().requestDisallowInterceptTouchEvent(false);
return false;
default:
}
return true;
}
return false;
}
}
Sample using this approach of a drag and drop is here