Hi, this is actually 2 questions.
I have a list of items stored in one string array and a list of the collections those items are in stored in a second string array.
I want the user to be able to search for an item and see in which collection it exists.
I have managed to do this in a less-than-elegant way by simply combining the 2 string arrays into one and using a ListView with a EditText with a TextWatcher to filter the results. This all works but the result is not so eye-pleasing. I use this to make the distinction between item and collections:
Code:
<item>ITEM \r\n -> COLLECTION(S)
when defining the string array.
As I said, it works but I would like the COLLECTION(S) to be formatted differently from the ITEM. Is this possible in a ListView?
This is my current code:
Code:
public class Search extends Activity {
/** Called when the activity is first created. */
private ListView lv1;
private EditText ed;
private String[] lv_arr;
private ArrayList<String> arr_sort= new ArrayList<String>();
int textlength=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
lv1=(ListView)findViewById(R.id.listView1);
ed=(EditText)findViewById(R.id.editText1);
lv_arr = getResources().getStringArray(R.array.all_cont);
lv1.setAdapter(new ArrayAdapter<String>(this, R.layout.row , lv_arr));
ed.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
textlength=ed.getText().length();
arr_sort.clear();
for(int i=0;i<lv_arr.length;i++)
{
if(textlength<=lv_arr[i].length())
{
if(ed.getText().toString().equalsIgnoreCase((String) lv_arr[i].subSequence(0, textlength)))
{
arr_sort.add(lv_arr[i]);
}}}
lv1.setAdapter(new ArrayAdapter<String>(Search.this, R.layout.row , arr_sort));
}
});
}}
As a second solution that looks more elegant, I used a SimpleAdapter to put the 2 original string arrays in the ListView like this:
Code:
public class Search extends ListActivity {
private String[] l1;
private String[] l2;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.seach);
ArrayList<Map<String, String>> list = buildData();
String[] from = { "name", "packs" };
int[] to = { android.R.id.text1, android.R.id.text2 };
SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, from, to);
setListAdapter(adapter);}
private ArrayList<Map<String, String>> buildData() {
l1 = getResources().getStringArray(R.array.items);
l2 = getResources().getStringArray(R.array.packs);
Integer i;
int to = l1.length;
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
for(i=0;i < to;i++){
list.add(putData(l1[i], l2[i]));
}
return list;
}
private HashMap<String, String> putData(String name, String packs) {
HashMap<String, String> item = new HashMap<String, String>();
item.put("name", name);
item.put("packs", packs);
return item;
}
}
This looks a lot better but I can't figure out how to make use of the EditText to filter the results.
Any help is welcomed!
Hey!
I read your post and I think it would be better to make a class like this:
Code:
public class ListItem
{
public String itemName;
public String collectionName;
}
And then in your Search activity you can Make a single ArrayList of the type ListItem. Populate this array in a way similar to how you are populating the ArrayList of the HashMaps.
Now for setting the ListAdapter you'll have to make a custom view for each row of the list(this custom row could contain two text views, one for the item name and the other for the collection and you can give them their own formatting), and then subclass the ArrayAdapter class and override its getView method.
Heres a couple of links that might be helpful:
http://www.ezzylearning.com/tutoria...droid-listview-items-with-custom-arrayadapter
http://stackoverflow.com/questions/2265661/how-to-use-arrayadaptermyclass
Hope this helps
The_R said:
Hey!
I read your post and I think it would be better to make a class like this:
Code:
public class ListItem
{
public String itemName;
public String collectionName;
}
And then in your Search activity you can Make a single ArrayList of the type ListItem. Populate this array in a way similar to how you are populating the ArrayList of the HashMaps.
Now for setting the ListAdapter you'll have to make a custom view for each row of the list(this custom row could contain two text views, one for the item name and the other for the collection and you can give them their own formatting), and then subclass the ArrayAdapter class and override its getView method.
Heres a couple of links that might be helpful:
http://www.ezzylearning.com/tutoria...droid-listview-items-with-custom-arrayadapter
http://stackoverflow.com/questions/2265661/how-to-use-arrayadaptermyclass
Hope this helps
Click to expand...
Click to collapse
Thanks once more. I looked over the links and I think I have an idea of how to adapt it to my app. Will try it tomorrow and let you know
Yeah. Let me know if it worked.
The_R said:
Yeah. Let me know if it worked.
Click to expand...
Click to collapse
I feel like my head is exploding.
I did what you said but I still have some issues. Here's what I did:
1. Created a new class, Icons:
Code:
public class Icons {
public String icon;
public String title;
public Icons(){
super();
}
public Icons(String icon, String title) {
super();
this.icon = icon;
this.title = title;
}
}
Created a new XML for the style of the ListView:
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/icon_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textSize="18sp"
android:textColor="#ffffff"
android:textStyle="bold" />
<TextView
android:id="@+id/in_pack"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textSize="12sp" />
</LinearLayout>
created a new Adapter:
Code:
public class IconsAdapter extends ArrayAdapter<Icons>{
Context context;
int layoutResourceId;
Icons data[] = null;
public IconsAdapter(Context context, int layoutResourceId, Icons[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
IconsHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new IconsHolder();
holder.txtIcon = (TextView)row.findViewById(R.id.icon_name);
holder.txtTitle = (TextView)row.findViewById(R.id.in_pack);
row.setTag(holder);
}
else
{
holder = (IconsHolder)row.getTag();
}
Icons icons = data[position];
holder.txtTitle.setText(icons.title);
holder.txtIcon.setText(icons.icon);
return row;
}
static class IconsHolder
{
TextView txtIcon;
TextView txtTitle;
}
}
Modified my Search class like this:
Code:
public class Search extends Activity {
private ListView listView1;
private String[] l1;
private String[] l2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.seach);
l1 = getResources().getStringArray(R.array.items);
l2 = getResources().getStringArray(R.array.packs);
Integer i;
int to = l1.length;
// for(i=0;i < to;i++){}
Icons Icons_data[] = new Icons[]
{
new Icons(l1[0], l2[0]),
new Icons(l1[1], l2[1]),
new Icons(l1[2], l2[2]),
new Icons(l1[3], l2[3]),
};
IconsAdapter adapter = new IconsAdapter(this,
R.layout.row, Icons_data);
listView1 = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.row, null);
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
}
}
Up until now, everything works (almost) great. Only thing I can't do is figure out how to assign the items in the Icons_data[] array automatically (my for(...) statement doesn't seem to want to fit anywhere). Format looks good and manually inserting data does what it's supposed to. Still need to figure out the automatic data inserting thing...my arrays have 100-150 elements
What I also can't figure out is how the hell to perform the filtering/search on this new special Array... I tried using the old method with the TextWatcher on an EditText field but can't seem to be able to adapt this part:
Code:
public void onTextChanged(CharSequence s, int start, int before,
int count) {
textlength=ed.getText().length();
[B][U]arr_sort.clear();[/U][/B]
for(int i=0;i<to;i++)
{
if(textlength<=l1[i].length())
{
if(ed.getText().toString().equalsIgnoreCase((String) l1[i].subSequence(0, textlength)))
{
[B][U]arr_sort.add(l1[i]);[/U][/B]
}
}
}
[B][U]lv1.setAdapter(new ArrayAdapter<String>(Search.this, R.layout.row , arr_sort))[/U][/B];
}
});
ed is the EditText item. I guess I would need to make arr_sort of the type Icons[] and then change the Bold, Underlined lines to something...but no idea what... Is it even possible to do it like i'm doing it? Or should I look for another method to sort it?
Hey I modified your search class:
Code:
public class Search extends Activity {
private ListView listView1;
// Note: I've removed the two String[] class members cause we are going
// store this data in a single Icons[] member
private Icons[] iconsData;
private ArrayList<Icons> arr_sort; // Note: Changed the type of arr_sort
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.seach);
// We'll create two local String[] variables to assemble the data
String[] l1 = getResources().getStringArray(R.array.items);
String[] l2 = getResources().getStringArray(R.array.packs);
// get the total number of icons
int totalIcons = l1.length;
// Allocate the data for the Icon[] array
iconsData = new Icons[totalIcons];
// Now to populate the Icon array
for (int i = 0; i < totalIcons; i++)
{
iconsData[i] = new Icons(l1[i], l2[i]);
}
// Rest remains the same
IconsAdapter adapter = new IconsAdapter(this,
R.layout.row, iconsData);
listView1 = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.row, null);
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
}
}
Now you don't need to change the sorting method. Just slight modifications to fit the data structuring is all that is needed.
Code:
public void onTextChanged(CharSequence s, int start, int before, int count)
{
textlength = ed.getText().length();
arr_sort.clear();
for(int i = 0 ; i < to; i++)
{
if(textlength <= iconsData[i].icon.length()) //Note: l1 becomes iconsData[i].icon
{
if(ed.getText().toString().equalsIgnoreCase((String) iconsData[i].icon.subSequence(0, textlength)))
{
arr_sort.add(iconsData[i]); // Note: we'll store iconsData[i] if a match is found
}
}
}
lv1.setAdapter(new IconsAdapter(Search.this, R.layout.row , arr_sort.toArray()));
}
Haven't tested it. So watch out for some possible errors.
I can't thank you enough but I still need your help.
The first part works (modifications to the Search class).
Now, In the same class, after that part, I add the filtering part:
Code:
ed=(EditText)findViewById(R.id.editText1);
ed.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
int textlength = ed.getText().length();
arr_sort.clear();
for(int i=0;i<[B][I]totalIcons[/I][/B];i++)
{
if(textlength <= iconsData[i].icon.length()) //Note: l1 becomes iconsData[i].icon
{
if(ed.getText().toString().equalsIgnoreCase((String) iconsData[i].icon.subSequence(0, textlength)))
{
arr_sort.add(iconsData[i]); // Note: we'll store iconsData[i] if a match is found
}
}
}
listView1.setAdapter(new IconsAdapter(Search.this, R.layout.row , [U][B](Icons[])[/B][/U] arr_sort.toArray()));
}
});
}
}
I had to make 2 changes in order for it not to give any errors. First, I changed the "to" in the for statement to "totalIcons" since that's actually the number we need and "to" was not defined. When I did this I also had to change "totalIcons" to final int since I had this error:"Cannot refer to a non-final variable totalIcons inside an inner class defined in a different method"
Also, I had to add the (Icons[]) at the end because of this error: "The constructor IconsAdapter(Search, int, Object[]) is undefined". The suggested fixes was changing the constructor for IconsAdapter, adding a new constructor or adding the (Icons[]) thing.
Now I have no errors in Eclipse but when I run the app and try to type something in the EditText box the app crashes...I get these errors:
04-12 19:32:27.032: E/AndroidRuntime(998): FATAL EXCEPTION: main
04-12 19:32:27.032: E/AndroidRuntime(998): java.lang.NullPointerException
04-12 19:32:27.032: E/AndroidRuntime(998): at mmarin.iconpack.manager.Search$1.onTextChanged(Search.java:70)
04-12 19:32:27.032: E/AndroidRuntime(998): at android.widget.TextView.sendOnTextChanged(TextView.java:6295)
04-12 19:32:27.032: E/AndroidRuntime(998): at android.widget.TextView.handleTextChanged(TextView.java:6336)
04-12 19:32:27.032: E/AndroidRuntime(998): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6485)
04-12 19:32:27.032: E/AndroidRuntime(998): at android.text.SpannableStringBuilder.sendTextChange(SpannableStringBuilder.java:889)
Sorry about the previous untested code. I was in a rush to go somewhere but I saw you online and thought that it'd be better if I replied.
Anyways, I think the problem is that "totalIcons" is a local variable. So remove the final keyword. And in the for loop in the TextWatcher's onTextChanged method instead of using totalIcons use the length property of iconsData:
Code:
for (int i = 0; i < iconsData.length; i++)
Should fix the runtime error
First off, please do all the things you have to do and don't waste your time with me. I really really appreciate you trying to help me so if you don't have time for this, it's absolutely no problem.
Now, the runtime errors are still there after the change
04-12 19:59:24.332: E/AndroidRuntime(1034): FATAL EXCEPTION: main
04-12 19:59:24.332: E/AndroidRuntime(1034): java.lang.NullPointerException
04-12 19:59:24.332: E/AndroidRuntime(1034): at mmarin.iconpack.manager.Search$1.onTextChanged(Search.java:70)
04-12 19:59:24.332: E/AndroidRuntime(1034): at android.widget.TextView.sendOnTextChanged(TextView.java:6295)
04-12 19:59:24.332: E/AndroidRuntime(1034): at android.widget.TextView.handleTextChanged(TextView.java:6336)
04-12 19:59:24.332: E/AndroidRuntime(1034): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6485)
04-12 19:59:24.332: E/AndroidRuntime(1034): at mmarin.iconpack.manager.Search$1.onTextChanged(Sea rch.java:70)
Can you paste line 70 of Search.java?
Wait are you doing this in onCreate?
Code:
arr_sort = new ArrayList<Icons>();
That's what I was looking for (actually how to enable line numbers in Eclipse )
here it is:
Code:
arr_sort.clear();
Yep. We aren't creating arr_sort. So its a null pointer.
Do this somewhere in onCreate
Code:
arr_sort = new ArrayList<Icons>();
ok, that solved that issue. now the problem is with this:
Code:
listView1.setAdapter(new IconsAdapter(Search.this, R.layout.row, (Icons[]) arr_sort.toArray()));
What error/exception do you get?
04-12 20:17:26.663: E/AndroidRuntime(1205): FATAL EXCEPTION: main
04-12 20:17:26.663: E/AndroidRuntime(1205): java.lang.ClassCastException: [Ljava.lang.Object;
04-12 20:17:26.663: E/AndroidRuntime(1205): at mmarin.iconpack.manager.Search$1.onTextChanged(Search.java:84)
I guess that the arr_sort.toArray() creates an Object[] but we need a Icons[] resource for the IconsAdapter.
Am I close?
Yea you are right
One quick and ugly solution I can think of is maybe creating an Icons array right after the search and then filling it with all the items in the arraylist. This happens right before you are setting the adapter
Code:
Icons[] data = new Icons[arr_data.size()];
for (int i = 0; i < arr_data.size(); i++)
{
data[i] = arr_data.get(i);
}
listView1.setAdapter(new IconsAdapter(Search.this, R.layout.row, data));
This should work but it isn't really a good solution =/
Quick and ugly works for me! You're 3 for 3!
You get a big special thanks in my App!!!
Once more, thank you and probably I will ask for your help again in a short while, with another issue I can't figure out.
It will probably be about getting a market link for an app through the Share menu in the Play Store and using that information to send an e-mail - but I will try to figure it out for myself . I already found how to get my app in the "Share" menu in the Play Store and also (possibly) how to save that information to a string. Now i have to find out how to actually get my app to start a certain Activity when it is started by the Play Store app. Will do that over the weekend
Sure! I'll be happy to help out with whatever little bit know!
Sorry for my bad english, but i have problem and can't figure it out..
I have custom listview in my fragment for getting products from JSON array. And I have 3 ImageButtons in every listview row;
Plus Button(+), Minus Button(-) and Remove Button(X)..
So when i click each button, its calling JSON request for update product's piece number, getting new datas from response and repopulate array list.
Everything ok but, when I click that buttons faster, it seems there is 1 sec delay between multiple requests even first volley request has already done before.
Here is my JSON method in TableAdapter.java
Code:
[SIZE="3"]public void JSON(final int position, final int process) {
if (inProgress==false) {
dialog = new ProgressDialog(myContext);
dialog.setMessage("Updating.....");
dialog.show();
inProgress = true;
System.out.println("**** Now request is beginning............");
final int rowID = tableModelList.get(position).getID();
final int treeID = tableModelList.get(position).getAna_dal();
final float price = tableModelList.get(position).getBFiyat();
final int quantity = tableModelList.get(position).getAdet();
final int print = tableModelList.get(position).getYazdimi();
final String insertUrl = "This is URL for getting json array";
Map<String, String> parameters = new HashMap<>();
parameters.put("tableID", "" + getTableId);
parameters.put("rowID", "" + rowID);
parameters.put("treeID", ""+treeID);
parameters.put("process",""+process);
parameters.put("quantity",""+quantity);
parameters.put("price",""+price);
parameters.put("print",""+print);
CustomRequest jsObjRequest = new CustomRequest(Request.Method.POST, insertUrl, parameters, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray getOrders = response.getJSONArray("order");
Gson gson = new Gson();
tableModelList.clear();
for (int i = 0; i < getOrders.length(); i++) {
JSONObject order = getOrders.getJSONObject(i);
TableModel tableModel = gson.fromJson(order.toString(), TableModel.class);
tableModelList.add(tableModel);
}
mAdapter.notifyDataSetChanged();
System.out.println("**** onResponse: Request is done............");
System.out.println("**** JSON: "+response.toString());
dialog.cancel();
inProgress = false;
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError response) {
Log.d("Response: ", response.toString());
inProgress = false;
}
});
requestQueue.add(jsObjRequest);
}
}[/SIZE]
Dialog is showing when request beginning and canceling when request is done. But as I said, when I click faster, there is a delay between multiple requests even first request has already done. I'm saying 1 sec, because 2nd request is beginning after 1 sec exactly, no matter how I clicking fast. I can't figure it out..
I tested fast clicks to showing toasts with random numbers and it's working fine. But when I testing with JSON method, there is a weird delay.
I have SwipeRefreshLayout and ScrollView in my fragment. I'm using Volley with singleton.
Here is video to showing what my problem is;
Here is Logcat output for every click
Every fast click has returning success json output, but nothing change instantly on the screen..
Thanks for your help.
I need to do some image processing in real time on mobile. I am using camera2 library. I managed to put camera preview directly on surfaceView but when i redirect it to ImageReader to do something with frames before i preview them it goes really slow, and there is not even processing just taking Y value from YUV_420_888 and converting it to gray picture in ARGB_8888 format. Code is below. For that one for loop i need about 600ms. And for image processing i will need to go trough that image at least one more time. In Bits array i form ARGB_8888 format out of Y array which is Y value of YUV_420_888 format. I test it on phone with Quad Core 1ghz processor and 1gb ram. Is there any way to speed this code up so i can go lets say 2-3 times trough picture and have at least 7-10 fps? If i delete for loop and just measure fps its 8-12fps. Why is it so slow compering to 25fps when i put it directly on surfaceView?
Code:
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
// This method is called when the camera is opened. We start camera preview here.
mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
createCameraPreviewSession();
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if(image != null) {
ByteBuffer buffer0 = image.getPlanes()[0].getBuffer();
byte[] Y = new byte[buffer0.remaining()];
buffer0.get(Y);
byte[] Bits = new byte[Y.length*4]; //That's where the RGBA array goes.
int Ylength = Y.length;
for (int i = 0; i < Ylength; i++) {
int i1 = i*4;
Bits[i1] =Y[i];
Bits[i1 + 1] =Y[i];
Bits[i1 + 2] = Y[i];
Bits[i1 + 3] = -1;//0xff, that's the alpha.
}
Bitmap bm = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));
Bitmap scaled = Bitmap.createScaledBitmap(bm, surfaceView.getWidth(), surfaceView.getHeight(), true);
Canvas c;
c = surfaceHolder.lockCanvas();
c.drawBitmap(scaled, 0, 0, null);
surfaceHolder.unlockCanvasAndPost(c);
image.close();
time2 = System.nanoTime();
Log.d("Vreme",Double.toString(1000000000/(time2-time1))+"fps");
time1 = System.nanoTime();
}
}
},mBackgroundHandler);
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};