This question already has answers here:
Random shuffling of an array
(31 answers)
Closed 2 years ago.
I'm working in Java code, but I can not figure out how to shuffle my images and text. Here is all of my coding. They are in different classes so I will post them separately. This is in Android Studio.
This is my ImageandTextAdapter code:
public class ImageAndTextAdapter extends ArrayAdapter<String> {
private LayoutInflater mInflater;
private String[] mStrings;
private TypedArray mIcons;
private int mViewResourceId;
public ImageAndTextAdapter (Context ctx, int ViewResourceId, String[] strings, TypedArray icons) {
super(ctx, ViewResourceId, strings);
mInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mStrings = strings;
mIcons = icons;
mViewResourceId = ViewResourceId;
}
#Override
public int getCount () { return mStrings.length; }
#Override
public String getItem(int position) {return mStrings[position]; }
#Override
public long getItemId(int position) {return 0; }
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
ImageView iv = (ImageView) convertView.findViewById(R.id.imageView);
iv.setImageDrawable(mIcons.getDrawable(position));
TextView tv = (TextView)convertView.findViewById(R.id.textView);
tv.setText(mStrings[position]);
return convertView;
}
}
This is my picture array code:
<resources>
<array name="card_faces">
<item>#drawable/b01</item>
<item>#drawable/b02</item>
<item>#drawable/b03</item>
<item>#drawable/b04</item>
<item>#drawable/b05</item>
<item>#drawable/b06</item>
<item>#drawable/b07</item>
<item>#drawable/b08</item>
</array>
</resources>
This is my main activity code:
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context context = getApplicationContext();
Resources resources = context.getResources();
String[] card = {"Blue1", "Blue2", "BlueSnake", "Blue4", "Blue5", "Blue6", "Blue7", "BlueHawk"};
TypedArray card_faces = resources.obtainTypedArray(R.array.card_faces);
setListAdapter(new ImageAndTextAdapter (context, R.layout.secondary_layout, card, card_faces));
}
}
I want to shuffle my pictures which are set in the array, but I am not able to with the Collections.shuffle command. If you know of a way that I could shuffle my pictures using a different and simple method, please help.
You can do it by converting the array to list and shuffle and then convert back to array
String[] card = {"Blue1", "Blue2", "BlueSnake", "Blue4", "Blue5", "Blue6", "Blue7", "BlueHawk"};
List<String> cardList = Arrays.asList(card);
Collections.shuffle(cardList);
cardList.toArray(card);
if you don't want to use more space you can try using random number generator to shuffle manually.
private static <T> void shuffle(T[] input){
Random rand = new Random();
for (int i = 0; i < input.length; i++) {
swap(input, i, rand.nextInt(input.length));
}
}
private static <T> void swap(T[] input, int x, int y){
T tmp = input[x];
input[x] = input[y];
input[y] = tmp;
}
Edit
If you want to shuffle the images which are inside a TypedArray, Instead of shuffling the string you can simply create an array of int with index and shuffle them then use its position for both string and images.
don't shuffle the string
List<Integer> indexes = new ArrayList<>();
for(int i = 0; i < indexes.length; i++){
indexes.add(i);
}
Collections.shuffle(indexes);
While using
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
int newPosition = indexes.get(position);
ImageView iv = (ImageView) convertView.findViewById(R.id.imageView);
iv.setImageDrawable(mIcons.getDrawable(newPosition));
TextView tv = (TextView)convertView.findViewById(R.id.textView);
tv.setText(mStrings[newPosition]);
return convertView;
}
Related
I have a ListView fulfilled with arrayList finalArray.
finalArray items are objects , each object
consisting of two TwxtViews - swedish word and its english translation
(all taken from 2 arrayLists - swedishPractice and englishPractice).
I have made EditText theFilter in order to search through the ListView,
but when I type anythong in theFilter all the items desappear from
the screen and nothing is found (whereas matches have to remain).
Why so and how to make matches remain?..
(When I made a ListView with objects containing
only 1 TextView, everything worked.)
That's how is object Word created:
public class Word {
private String swedish;
private String english;
public Word(String swedish, String english) {
this.swedish = swedish;
this.english = english;
}
public String getSwedish() {
return swedish;
}
public void setSwedish(String swedish) {
this.swedish = swedish;
}
public String getEnglish() {
return english;
}
public void setEnglish(String english) {
this.english = english;
}
}
That's how I made the ListView:
ListView mListView = (ListView) findViewById(R.id.switchList);
EditText theFilter = (EditText) findViewById(R.id.searchFilter);
Log.d(TAG, "onCreate: Started");
ArrayList<Word> finalArray = new ArrayList<Word>();
for (int i = 0; i < Practice.swedishPractice.size(); i++) {
finalArray.add(new Word(Practice.swedishPractice.get(i),Practice.englishPractice.get(i)));
}
adapter = new CheckListAdapter(this, R.layout.list_item_layout, finalArray, this);
mListView.setAdapter(adapter);
theFilter.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
(VisaEj.this).adapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
});
And this is its adapter (in case you need to see it to give an answer)
(made in separate class):
public class CheckListAdapter extends ArrayAdapter<Word> {
private static final String TAG = "CheckListAdapter";
private Context mContext;
private int mResource;
private int lastPosition = -1;
/**
* Hold variables in a view
*/
static class ViewHolder {
TextView swedish;
TextView english;
}
/**
* Default constructor for the CheckListAdapter
* #param context
* #param resource
* #param objects
*/
public CheckListAdapter(#NonNull Context context, int resource, #NonNull ArrayList<Word> objects, Context mContext) {
super(context, resource, objects);
this.mContext = mContext;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
//get the word two examples
String swedish = getItem(position).getSwedish();
String english = getItem(position).getEnglish();
//create the word object with two examples
Word word = new Word(swedish, english);
//create the view result for showing the animation
final View result;
//Viewholder object
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
holder = new ViewHolder();
holder.swedish = (TextView) convertView.findViewById(R.id.textView1);
holder.english = (TextView) convertView.findViewById(R.id.textView2);
result = convertView;
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
result = convertView;
}
Animation animation = AnimationUtils.loadAnimation(mContext,
(position > lastPosition) ? R.anim.loading_down_anim : R.anim.loading_up_anim);
result.startAnimation(animation);
lastPosition = position;
holder.swedish.setText(word.getSwedish());
holder.english.setText(word.getEnglish());
return convertView;
}
}
I want to hide the 2nd option from the list on switch on off, I know how switch works, just tell me how to hide-unhide the option from the list. I want to hide list view item by item position or something like that.
New query : Is it possible to add two different adapter and switch them on switch preference change? if yes then how to do that?
This is 100% possible.
String [] titles = {"abc","def","ghi"};
String [] descriptions = {"abc","def","ghi"};
int [] images = {R.drawable.ic_abc,R.drawable.ic_def,R.drawable.ic_ghi};
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
lv = (ListView) findViewById(R.id.listView);
final Adapter adapter = new Adapter(getApplicationContext(), titles, descriptions, images);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
List view adapter
class Adapter extends ArrayAdapter {
int[] imageArray;
String[] titleArray;
String[] descriptionArray;
public Adapter(Context context, String[] titles1, String [] description1, int[] img1) {
super(context, R.layout.list_row, R.id.Titles, titles1);
this.imageArray = img1;
this.titleArray = titles1;
this.descriptionArray = description1;
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.list_row,parent,false);
ImageView myImage = (ImageView) row.findViewById(R.id.Icons);
TextView myTitle = (TextView) row.findViewById(R.id.Titles);
TextView myDescription = (TextView) row.findViewById(R.id.Descriptions);
myImage.setImageResource(imageArray[position]);
myTitle.setText(titleArray[position]);
myDescription.setText(descriptionArray[position]);
return row;
}
}
Switch preference
public SwitchPreference sw;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_sw);
sw = (SwitchPreference) findPreference("001");
}
on switch on/off in main activity
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean sw = sharedPreferences.getBoolean("001", true);
if (sw) {
//hide list view item (only one)
} else {
//unhide list view item (only one)
}
Well, take a look, so you can call remove properly:
class Adapter extends ArrayAdapter {
List<ItemObject> data = new ArrayList();
public Adapter(Context context, String[] titles1, String [] description1, int[] img1) {
super(context, R.layout.list_row, R.id.Titles, titles1);
for(int i = 0; i < titles1.lenght; i++)
data.add(new ItemObject(titles1[i], description1[i], img1[i]);
}
static class ItemObject {
String title, description;
int image;
ItemObject(String ti, String desc, int img) {
title = ti;
description = desc;
image = img;
}
}
//plus the rest of your class
And change at getView
ItemObject row = data.get(position);
myImage.setImageResource(row.image);
myTitle.setText(row.title);
myDescription.setText(row.description);
And add this method in the adapter:
public void removeObject(int at) {
data.remove(at);
notifyDataSetChanged();
}
So you can call removeObject with a position.
What pattern do I have to use, if I have ListView in which ImageView and like 500 different icons that could be set on that ImageView. Should I just write If/Switch statement, or there is another way/pattern to do it?. Thanks in advance!
Let me assume that you know what icon(I mean the name of icon) to be loaded into the imageView and those icons are available in your drawable resource folder. In this case
#Override
public void onBindViewHolder(final RecyclerAdapter.ViewHolder holder, int position) {
DataItem dataItem = dataList.get(holder.getAdapterPosistion());
try {
int resID = activityContext.getResources().getIdentifier(dataItem.getIconName() , "drawable"/**resource folder name*/, activityContext.getPackageName());
holder.imageView.setBackgroundResource(resID);
} catch (Exception e) {
throw new RuntimeException("Error getting Resource ID.", e)
}
}
Where are these icons that you want to set? you are getting them from server or they are stored locally in your application file? or they are from user phone gallery?
Here is the code you want for your adapter:
public class MyAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<String> mIconNames;
public MyAdapter(Context context) {
mContext = context;
mIconNames = getIconNames();
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mIconNames.size();
}
#Override
public Object getItem(int position) {
return mIconNames.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get view for row item
View rowView = mInflater.inflate(R.layout.your_layout, parent, false);
ImageView thumbnailImageView =
(ImageView) rowView.findViewById(R.id.your_image_view_id);
Picasso.with(mContext).load(mIconNames.get(position)).placeholder(R.mipmap.ic_launcher).into(thumbnailImageView);
return rowView;
}
//this method builds your icon names
private ArrayList<String> getIconNames() {
ArrayList<String> iconNames = new ArrayList<>();
int numberOfIcons = 99;
String iconBaseName = "icon";
for (int i = 1; i < numberOfIcons; i++) {
iconNames.add(iconBaseName + i);
}
return iconNames;
}
}
The current project I have includes a ListView with a Custom Adapter. However, I am now interested in adding multiple types of views to my ListView but after several attempts I have been unable to add the two sources of code together to successfully integrate them.
Article on ListView with multiple views: ListView Article for multiple views
The custom adapter in my current code retrieves the data from another class called getData which is referenced by "data".
Code from article (ListView with multiple views):
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
private TreeSet mSeparatorsSet = new TreeSet();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
Current code (ListView with custom adapter):
FragmentA.java
package com.example.newsapp;
public class FragmentA extends Fragment{
getData data = getData.getMyData();
public Integer ArticleID;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment_a, container, false);
ListView listView = (ListView)V.findViewById(R.id.list)
CustomList adapter = new
CustomList(getActivity(), data.Headline.toArray(new String[data.Headline.size()]), data.Description.toArray(new String[data.Description.size()]), data.BitmapList.toArray(new Bitmap[data.BitmapList.size()]), data.ArticleID.toArray(new Integer[data.ArticleID.size()]));
listView.setAdapter(adapter);
listView.setOnItemClickListener(this); //Removed on click item event code.
return V;
}
CustomList.java
package com.example.newsapp;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
return rowView;
}
}
Edit:
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
int viewType = getItemViewType(position);
View rowView = null;
switch(viewType) {
case 0:
LayoutInflater inflater = context.getLayoutInflater();
rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
case 1:
LayoutInflater inflater2 = context.getLayoutInflater();
rowView= inflater2.inflate(R.layout.single_row_loadmore, null, true);
}
return rowView;
}
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
}
First, a bit of an aside: you should create a class that encapsulates a headline, description, etc. and use an array/collection of those objects to back your adapter. It will be far easier than managing many disparate arrays of things, especially if one day you decide you need another attribute of an Article (its category, for example).
class Article {
int id;
String headline;
String description;
Bitmap picture;
}
With regard to your ListView, the magic happens in the methods getItemViewType() and getViewTypeCount(). In getViewTypeCount() you return the maximum number of row types -- the article you posted uses two row types and so returns 2. In getItemViewType() you return a value between zero and (viewTypeCount - 1) -- in the article, his implementation can return 0 or 1 because his viewTypeCount is 2.
How you decide which row type applies to each item is entirely up to you. If, for example, you wanted to simply alternate view types on every row, you can do this:
#Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
#Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
In other applications you would probably inspect the item at the given position to help you determine what should be returned in getItemViewtype().
The reason this functionality exists is that getView() provides a parameter (called convertView) that is a row which has been recycled. In order to give you an appropriate convertView, ListView needs to first know what row type it was. When you want to implement getView() for an adapter with multiple row types, it generally looks something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
switch(viewType) {
case 0:
return setUpOneViewType(position, convertView, parent);
case 1:
return setUpAnotherViewType(position, convertView, parent);
}
}
Note the cases for the switch statement correspond to the possible values that can be returned from getItemViewType(). These could be static final members.
I highly suggest watching The World of ListView. That video covers this topic as well as how to properly use convertView in your adapter implementation.
I want to create an array which contains number of images. Later on I have to use that array in a loop in my code. Can anyone suggest if I can create an array of images.?
define a array of image id like this
int[] p = {R.drawable.image1, R.drawable.image2....}
now for different condition use member of this array like
yourbutton.setBackgroundResource(p[0]) // or p[1]
or you can use ENUM to make it more readable..
this will solve you problem:
int imageArray[] = new int[number_of_images];
for (int i = 0; i < numImages; i++)
imageArray[i] = getDrawableId(getApplicationContext(),"R.drawable." + image_names[i]);
You can define an array of image filenames :
String fileNames[] = {"temp.jpg", "sample_img28.jpg", "normImg.jpg", "drawing.png", "film.png"};
and add those in MeidaTracker while initializing the application
MediaTracker tracker = null;
public void init() {
tracker = new MediaTracker(this);
for(int i = 0; i < fileNames.length; i++) {
System.out.println(" path :"+this.getCodeBase());
image[i] = getImage(this.getCodeBase(),fileNames[i]);
image[i] = image[i].getScaledInstance(256, 256, Image.SCALE_SMOOTH);
tracker.addImage(image[i], i);
}
try {
tracker.waitForAll();
}
}
Create your own customImageAdapter extending ArrayAdapter.
Sample code for your arrayAdapter:
public class CustomImageAdapter extends BaseAdapter{
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public CustomImageAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
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;
}
// if you want to display the image modify the content according o your need
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image);//thumb image
return vi;
}