Note: As of Jellybean the gallery widget is deprecated. A ViewPager should be used instead.
I'd like to programmatically move between images in the Gallery widget, with animation.
I can change the currently displaying image using the setSelection(int position) method, however that does not animate. Then there's setSelection(int position, bool animate) but the extra boolean on the end there doesn't appear to do anything.
In the source of Gallery it appears that it can handle DPAD key-presses, so a work-around I thought of was to fake the key-presses. Eg.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT))
However I can't get this working for some reason. Anyone tried this?
I notice three of the widget's methods I'd love to use moveNext(), movePrevious() and scrollToChild() are all private and unusable.
Does anyone know how I might be able to do this?
Just call the key press handler for the gallery directly:
public boolean onKeyDown(int keyCode, KeyEvent event)
i.e
Gallery gallery = ((Gallery) findViewById(R.id.gallery));
gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(0, 0));
One important thing - this solution works only if child that is on left/right was already created, which means that it has to be 'visible'. If you have your image on fullscreen - consider setting spacing to -1 value.
You can Animate using dispatchKeyEvent or calling onFling directly.
Here is sample code for dispatchKeyEvent:
KeyEvent evtKey = new KeyEvent(0, KeyEvent.KEYCODE_DPAD_RIGHT);
dispatchKeyEvent(evtKey);
Use gallery.setSelected(int); Here is a simple example.
public class Splash extends Activity {
ArrayList objects = new ArrayList();
Gallery g;
int i = 0;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.photos);
g = (Gallery) findViewById(R.id.gallery);
objects.add(getResources().getDrawable(R.drawable.icon));
objects.add(getResources().getDrawable(R.drawable.icon));
objects.add(getResources().getDrawable(R.drawable.icon));
objects.add(getResources().getDrawable(R.drawable.icon));
objects.add(getResources().getDrawable(R.drawable.icon));
objects.add(getResources().getDrawable(R.drawable.icon));
g.setAdapter(new CustomAdapter(this, objects));
g.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView arg0, View arg1,
int arg2, long arg3) {
Log.i("", "selected " + arg2);
}
#Override
public void onNothingSelected(AdapterView arg0) {}
});
}
#Override
public void onBackPressed() {
g.setSelection(i++);
}
private class CustomAdapter extends BaseAdapter {
private Context mCtx;
private List objects;
public int getCount() {
return this.objects.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public CustomAdapter(Context context, ArrayList objects) {
super();
mCtx = context;
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView row = (ImageView) convertView;
if (row == null) {
row = new ImageView(mCtx);
row.setBackgroundDrawable(objects.get(position));
}
return row;
}
}
}
In the end I wrote my own version of the Gallery widget with the help of the code at this site.
I then wrote my own method which uses mFlingRunnable.startUsingDistance(distance);
Now I can programmatically animate the gallery between images.
Try this
mGallery.onFling(null,null, velocity,0);
http://groups.google.com/group/android-developers/browse_thread/thread/9140fd6af3061cdf#
Related
background
When choosing an item from a listView, I change its data and call notifyDataSetChanged.
The problem
Since it's the same listView, when I click the item, the effect stays for the view that will be used after the notifyDataSetChanged.
This is especially noticeable on Android Lollipop, where the ripple can continue after the listView gets refreshed with new data.
The code
Here's a sample code showing the problem:
public class MainActivity extends ActionBarActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView=(ListView)findViewById(R.id.listView);
listView.setAdapter(new BaseAdapter()
{
int pressCount=0;
#Override
public int getCount()
{
return 100;
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position)
{
return 0;
}
#Override
public View getView(int position,View convertView,ViewGroup parent)
{
View rootView=convertView;
if(rootView==null)
{
rootView=LayoutInflater.from(MainActivity.this).inflate(android.R.layout.simple_list_item_1,parent,false);
rootView.setBackgroundResource(getResIdFromAttribute(MainActivity.this,android.R.attr.selectableItemBackground));
rootView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
pressCount++;
notifyDataSetChanged();
}
});
}
TextView tv=(TextView)rootView;
tv.setText("text:"+(pressCount+position));
return rootView;
}
});
}
public static int getResIdFromAttribute(final Activity activity,final int attr)
{
if(attr==0)
return 0;
final TypedValue typedvalueattr=new TypedValue();
activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
return typedvalueattr.resourceId;
}
}
The question
How can I temporarily stop the selection effect till the next time anything is clicked on the listView (but also resume allowing it for the next time the user clicks an item) ?
OK, I've found the answer. It seems it's a known issue, and the solution is quite simple (shown here) :
ViewCompat.jumpDrawablesToCurrentState(view);
Weird thing is, it works for me only when I call it via Handler.post(...) .
Wonder why (as the view is already during animation), and if there's a better solution.
How do I have the menu pop up on a regular Card. I have tried to use this code:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
openOptionsMenu();
return true;
}
return false;
}
But it doesn't seem to work. Also, is it possible to put Live Cards in an Activity like I did here. I believe I am using Static Cards, but eventually I will need access to the camera and video functions through these Cards.
Activity
public class NewChecklistActivity extends Activity {
private GestureDetector mGestureDetector;
private List<Card> mCards;
private CardScrollView mCardScrollView;
StepCardScrollAdapter adapter;
Intent checklistIntent;
String allStepsJSONString;
ArrayList<String[]> allStepsArray;
ArrayList<String[]> checklistsArray;
ArrayList<String[]> stepsArray;
ArrayList<String[]> checklistSteps;
#SuppressWarnings("unchecked")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checklistsArray = (ArrayList<String[]>) this.getIntent().getSerializableExtra("checklists");
stepsArray = (ArrayList<String[]>) this.getIntent().getSerializableExtra("steps");
createCards();
mCardScrollView = new CardScrollView(this);
adapter = new StepCardScrollAdapter();
mCardScrollView.setAdapter(adapter);
mCardScrollView.activate();
setContentView(mCardScrollView);
mCardScrollView.setOnItemClickListener(adapter);
checklistIntent = new Intent(this, ChecklistActivity.class);
}
private void createCards() {
mCards = new ArrayList<Card>();
Card card;
String[] checklist;
for (int i = 0; i < checklistsArray.size(); i++) {
checklist = checklistsArray.get(i);
card = new Card(this);
card.setText(checklist[1]);
mCards.add(card);
}
}
private class StepCardScrollAdapter extends CardScrollAdapter implements OnItemClickListener {
#Override
public int findIdPosition(Object id) {
return -1;
}
#Override
public int findItemPosition(Object item) {
return mCards.indexOf(item);
}
#Override
public int getCount() {
return mCards.size();
}
#Override
public Object getItem(int position) {
return mCards.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return mCards.get(position).toView();
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
checklistIntent.putExtra("steps", getChecklistSteps(adapter.findItemPosition(position)));
startActivity(checklistIntent);
}
}
It looks like you're using a CardScrollView, which is going to intercept all of the touchpad gestures and that's why your onKeyDown method isn't getting called.
For this specific case, you can attach an OnItemClickListener to the card scroller and use that listener to find out when one of the cards is tapped. Then, call openOptionsMenu from there.
If you need to have different menu items for different cards, you'll need to store the index of the card that gets passed into the listener and then use that information inside onPrepareOptionsMenu to load different items. The flow would look like this:
You create a private field in your activity class that will store the index of the last tapped card.
In your onItemClick method, you store the index you're given in that field, and then you call openOptionsMenu.
This causes onPrepareOptionsMenu to be called. Override that method and do whatever modifications you need to the menu based on the index stored in that field (inflate a menu, add/remove items, etc.). You have to do this inside onPrepareOptionsMenu instead of onCreateOptionsMenu because you want it to happen every time the user taps, not just the first time the menu is initialized.
Handle onOptionsItemSelected as you normally would.
Is there any way to remove selected item from gridview.
I want to delete the selected item from my gridview.
I did not find any thing . my code is
public class ImageAdapter extends BaseAdapter{
Context context;
public ImageAdapter(Context context)
{
this.context = context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return mThumbIds.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 5, 0, 0);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
public Integer[] mThumbIds = {
R.drawable.sample_1,R.drawable.sample_2,R.drawable.sample_3,
R.drawable.sample_3,R.drawable.sample_1,R.drawable.sample_2,
R.drawable.sample_2,R.drawable.sample_3,R.drawable.sample_1
};
}
//////////////////
public class ImageActivity extends Activity {
ImageAdapter iAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
iAdapter = new ImageAdapter(this);
final GridView gView = (GridView)findViewById(R.id.grid_view);
gView.setAdapter(iAdapter);
gView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
//gView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// gView.setItemChecked(position, true);
Toast.makeText(ImageActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
iAdapter.notifyDataSetChanged();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_image, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.menu_delete)
{
Toast.makeText(this, "Delete",Toast.LENGTH_SHORT ).show();
}
return super.onOptionsItemSelected(item);
}
}
can anyone have idea .
thank
you are using a table :
public Integer[] mThumbIds = {
R.drawable.sample_1,R.drawable.sample_2,R.drawable.sample_3,
R.drawable.sample_3,R.drawable.sample_1,R.drawable.sample_2,
R.drawable.sample_2,R.drawable.sample_3,R.drawable.sample_1}
Tables are not modifiable.
Replace it by a List on which you will be able to make add or remove operations. Simply call notifyDataSetChanged when a change is made to let the adapter know that its list has been modified.
As Teovald and pskink suggested, you cannot have a fixed list of images and then implement the remove functionality that you are looking for. If you want to add remove, change your design and make sure your data set is also removable. What you have tried so far seems to be using some really basic code which is good to show basic GridView feature.
Just try this. Create a image data set class which returns the actual images. Store the images in a List that can be modified. Add setters/getters to this data set and also add a method to delete a particular item. Change your image adapter to use the image from this new data set. Whenever an image is deleted, call the notifyDataSetChanged on the adpater.
Good luck
I have a listview and a button in my layout file. I'am adding items to listview on click of that button. The listview should be empty when the activity is started but it should grow by adding the items to it.
This is my code inside onCreate() :
list = (ListView)findViewById(R.id.inverterListView);
adapter = new ArrayAdapter<String>(InverterList.this, R.layout.inverters_list_row, R.id.inverterNumberTextViewInPanelListRow);
list.setAdapter(adapter);
And here iam adding the items to listview onclick of a button.
adapter.add(inverterNo);
adapter.notifyDataSetChanged();
This works fine. Can anyone guide me to delete custom listview item ? Thanks in advance.
If you know the position of the item you can do this:
Object item = adapter.getItem(position);
adapter.remove(item);
adapter.notifyDataSetChanged();
You may write your own adapter extends BaseAdapter and implement all you need methods.
It is example of my adapter:
public class PeopleUserAdapter extends BaseAdapter
{
private List<User> users;
private int viewResourceId;
private Context context;
public PeopleUserAdapter(Context context, int viewResourceId)
{
this.context = context;
this.viewResourceId = viewResourceId;
this.users = new ArrayList<User>();
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
UserItemHolder holder;
if (convertView == null)
{
convertView = LayoutInflater.from(context).inflate(viewResourceId, parent, false);
holder = new UserItemHolder(convertView);
}
else holder = (UserItemHolder) convertView.getTag();
User user = getItem(position);
holder.name.setText("#" + user.getLogin());
return convertView;
}
#Override
public int getCount()
{
return users.size();
}
#Override
public User getItem(int position)
{
return users.get(position);
}
#Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}
public void clear()
{
users.clear();
}
public void addAll(Collection<User> users)
{
this.users.addAll(users);
notifyDataSetChanged();
}
public void replace(Collection<User> users)
{
clear();
addAll(users);
}
public static PeopleUserAdapter init(Context context)
{
return new PeopleUserAdapter(context, R.layout.item_user);
}
}
adapter.remove(item) .. and then call adapter.notifyDataSetChanged();
In case you are using a custom adapter (for a custom layout listview), you will want to do this:
When your Adapter is something like:
public class YourAdapterName extends ArrayAdapter<yourObject>
then the code for deleting the selected ListView Item will be:
ListView yourListView = (ListView) findViewById(R.id.listviewid);
YourAdapterName adapter;
adapter = (YourAdapterName) yourListView.getAdapter();
yourObject theitem = adapter.getItem(position);
adapter.remove(theitem);
adapte.notifyDataSetChanged();
This is assuming you are inside an event that gives you access to the current position inside the listview. like:
public boolean onItemLongClick(AdapterView<?> parent, View strings,int position, long id)
or
public void onItemClick(AdapterView<?> arg0, View v, int position, long id)
Otherwise you will need to obtain that position some other way, like storing it (onItemClick or onItemLongClick) in a textView with Visibility.GONE, and retrieve it when clicking the button (this is silly, you can use all kinds of storage options, like global variables, database and such).
Make sure you have overridden the remove method on your custom adapter
For example if this is your add method:
#Override
public void add(String[] object) {
scoreList.add(object);
super.add(object);
}
then your remove method would look something like this:
#Override
public void remove(String[] object) {
scoreList.remove(object);
super.remove(object);
}
call the below two lines::
adapter.remove(inverterNo);
adapter.notifyDataSetChanged();
where inverterNo is your item
It easy; you only to need is: add a method public in your personalize adapter some this:
public void remove(int position) {
itemsMovieModelFiltered.remove(position);
notifyDataSetChanged();
}
Remenber, this method you must add in your personalize adapter.
Then, call this method from other
adapte=new PersonalizeListAdapter(getActivity().getApplicationContext(),
movieModelList);
adapte.remove(position);
i have a big doubt about memory leak and screen rotation. I know that activity is destroy when that happens and new one is started. With my code, with is the best way to show the gridview? (this activity is part of a tab activity so in the main one i get the pictures from web services and put them on the object, using AsyncTask)
i would like to show the pictures at the same time they are saved on the object. Like simulating ajax...is that possible? at the moment, they are all show on the start or resume.
Also, im facing memory leak here?
last question, how can i show photos in the grid
my code:
public class LoteFotosActivity extends Activity {
Sistema sis=Sistema.getInstance();
Lote lote;
GridView gridview;
ImageAdapter iA;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lote_foto_view);
Bundle extras = getIntent().getExtras();
lote=sis.getLoteDetalle(extras.getInt("LoteID"));
gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(iA=new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(LoteFotosActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return lote.FOTOS.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200,200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageBitmap(lote.FOTOS.get(position));
return imageView;
}
}
//test looking
public void onResume() {
super.onResume();
Toast.makeText(this,"ON RESUME",
Toast.LENGTH_SHORT).show();
// gridview.setAdapter(new ImageAdapter(this));
// foto.setImageDrawable(lote.FOTOS.get(0));
}
public void onPause() {
super.onPause();
Toast.makeText(this,"onPause",
Toast.LENGTH_SHORT).show();
iA=null;
gridview.setAdapter(iA=new ImageAdapter(this));
// foto.setImageDrawable(lote.FOTOS.get(0));
}
thx in advance !
I think you should add this to your activity
android:configChanges="orientation"
to avoid the destroying problem when rotating the screen... with this you dont need to save state to restore, there is no need because the activity is not destroyed and recreated everytime the screen rotation changes
For API 13+ the screenSize must also be handled:
android:configChanges="orientation|screenSize"