I have an activity which generates a scrollable list (let's say a column) of programmatically created buttons from a List which is the result of an sqlite table read and my problem is that as the List is growing (and so the number of buttons) the initial painting of the screen is becoming slow (at the moment is taking 3 seconds with 50 buttons to draw) so I'm looking for a solution to this.
At first I thought of using a thread (runnable, handler or whatever is best), let's say creating a new thread inside the For which iterates over the list but it's not working (or at least I'm not being able to make it to work) so my question is the next:
Starting from a List<> which is the most appropiate way to create a big set of scrollable buttons so users doesn't have such delay when accesing the screen.
Paginating could be an option, but I'd like to know about other possibilities first and leave that as a last resource.
Thanks, and below is my code.
public static void createButtons(LinearLayout llContainer,
List<TestType> TestTypes, List<Test> Tests,
int buttonFontSize) {
Context oContext = llContainer.getContext();
String strTheme = TMAppearance.getThemeFromPreferences(oContext);
testMe = ((ApplicationConfiguration)oContext.getApplicationContext());
int callerActivity = TestTypes!=null ? 2 : 1;
if (TestTypes!=null || Tests!=null) {
int lCols = strTheme.equals(testMe.theme_vivid) ? 1 : 2;
//int sourceElementIndex = 0;
int originListSize = calculateOriginalListSize(callerActivity, TestTypes, Tests);
int lRows = (int) Math.ceil((double)originListSize/lCols);
List<String> aStartColors = TMUtils_ThemeVivid.generateStartColorArray(lRows, oContext);
List<String> aEndColors = TMUtils_ThemeVivid.generateEndColorArray(lRows, oContext);
for (i = 0; i < lRows; i++) {
LinearLayout outerButtonLayout = generateOuterButtonLayout(oContext);
for (j = 0; j < lCols; j++) {
final Thread r = new Thread() {
public void run() {
LinearLayout innerButtonLayout = generateInnerButtonLayout(oContext);
outerButtonLayout.addView(innerButtonLayout, j);
if (sourceElementIndex<originListSize){
final TMButton oButton = new TMButton(oContext);
if (callerActivity==1) { //testMenu
setTestMenuButtonSettings(oButton, sourceElementIndex, Tests);
} else {
if (callerActivity==2) { //testTypeMenu
setTestTypeMenuButtonSettings(oButton, sourceElementIndex, TestTypes);
}
}
if (strTheme.equals(testMe.theme_vivid)){
oButton.fontSize = buttonFontSize;
oButton.gradientStartColor = aStartColors.get(i);
oButton.gradientEndColor = aEndColors.get(i);
}else{
if (strTheme.equals(testMe.theme_purple)){
oButton.gradientStartColor = testMe.btnStartColor_purple;
oButton.gradientEndColor = testMe.btnEndColor_purple;
}
}
configureButton(oButton, callerActivity);
oButton.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Context oContext = v.getContext();
TMButton oButton = (TMButton) v;
int callerActivity = Integer.valueOf(v.getTag().toString().split("#")[0]);
String sourceId = String.valueOf(v.getTag().toString().split("#")[1]);
if(event.getAction() == MotionEvent.ACTION_DOWN) { //pressed
setButtonPressed(oButton);
TMSound.playButtonSound(oContext);
} else if (event.getAction() == MotionEvent.ACTION_UP) { //released
setButtonReleased(oButton);
startTargetActivity(callerActivity, sourceId, oContext);
}
return true;
}
});
TMAppearance.doButtonAnimation(oContext, oButton, i);
innerButtonLayout.addView(oButton);
sourceElementIndex++;
}
}
};
r.run();
}
llContainer.addView(outerButtonLayout);
}
}
}
0X0nosugar is correct. A RecycleView will provide better performance, but many beginners have more difficulty implementing it and with only 50 buttons performance shouldn't really be an issue. And although I generally like to abide by the rule 'Use the best available solution' I think it is still appropriate to learn how to implement the ListView. So...
You will need to create a custom adapter:
public class MyListDataAdapter extends ArrayAdapter<MyListData> {
private static final String TAG = "MyListDataAdapter";
public MyListDataAdapter(Context context, ArrayList<MyListData> data) {
super(context, 0, data);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
final MyListData data = getItem(position);
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.edit_list_item, parent, false);
}
// Add a TextView if you need one
final TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
Button btnEditTicketHolder = (Button) convertView.findViewById(R.id.btnEdit);
btnEditTicketHolder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
long userId = data.getUserId();
String fName = data.getFirstName();
Intent intent = new Intent(getContext(), EditActivity.class);
intent.putExtra("userId", userId);
intent.putExtra("fName", fName);
getContext().startActivity(intent);
}
});
String name = data.getFirstName();
tvName.setText(name);
return convertView;
}
}
Now you need your MyListData class to hold the data:
public class MyListData {
// Add more as you need
private long userId;
private String firstName;
public MyListData(){
}
public void setFirstName(String name){ this.firstName = name; }
public void setUserId(long id){ this.userId = id; }
public String getFirstName(){ return this.firstName; }
public long getUserId(){ return this.userId; }
}
Your custom ListView layout could look something like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
>
<TextView
android:id="#+id/tvName"
android:text="With Whom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
>
<Button
android:id="#+id/btnEdit"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:text="Edit"
android:backgroundTint="#color/colorAccent"
android:focusable="false"
/>
</LinearLayout>
</RelativeLayout>
In your Activity (eg. in the onCreate() method) where the ListView you will need to populate the data for the ListView. This should not be done on the UI Thread
ArrayList<MyListData> arrayListData = new ArrayList<MyListData>();
MyListDataAdapter adapter = new MyListDataAdapter(this, arrayListData);
for (MyListData g : result) {
adapter.add(g);
}
mLstMy.setAdapter(adapter);
Also in the activity where the ListView is to be maintained set up some onClick event handlers if you need them:
(I find that one of the small advantages of the ListView is that the onClick event is easier it implement than in the RecycleView)
mMyLst = (ListView) findViewById(lstMy);
mMyLst.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
MyListData data = (MyListData) parent.getItemAtPosition(position);
selectedName = data.getName();
Intent intent = new Intent(ShowListDataActivity.this, MainActivity.class);
startActivity(intent);
}
});
mMyLst.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
MyListData data = (MyistData) adapterView.getItemAtPosition(i);
selectedName = data.getFirstName();
selectedTicketPosition = i;
// removeValue is my own method for removing an entry from the
// list MyListData and then call adapter.notifyDataSetChanged();
removeValue(i);
return true;
}
});
Related
I have a listview that when I change the value of one item (count) with click on plus button, Everything is fine as long as the user do scroll down and show more items
And we see that on each page of the scroll has changed a value of item!!!
idont kNow why everything seems fine!!
public class MyAdapter extends BaseAdapter {
private String[] from;
ArrayList <HashMap<String, Object>> BuyList ;
private int[] to;
private Context context;
private ArrayList<HashMap<String, Object>> data ;
private ArrayList<HashMap<String, Object>> selecteddata;
private ArrayList<HashMap<String, Object>> fdata ;
private ImageView pay,more;
private EditText search;
private String user_mobile;
private TextView buy_toolbar_count;
private Holder holder;
// private HashMap<String, Object> hm;
public MyAdapter( Context context, ArrayList<HashMap<String, Object>> data,
ArrayList<HashMap<String, Object>> selecteddata , String[] from, int[] to, ArrayList Bylist,
ImageView pay, ImageView more, String user_mobile, TextView buy_count_toolbar, EditText search) {
this.data = data;
this.selecteddata = selecteddata;
this.fdata = new ArrayList<>(selecteddata);
this.context = context;
this.from = from;
this.to = to;
this.BuyList = Bylist;
this.pay = pay;
this.more = more;
this.search = search;
this.user_mobile = user_mobile;
this.buy_toolbar_count = buy_count_toolbar;
}
public void filter(String s, ImageView img) {
HashMap<String, Object> wp = new HashMap<>();
if (!s.equals("")) {
fdata.clear();
for (int i = 0 ;i<data.size();i++) {
wp = data.get(i);
// Log.i("mosi",wp.get("name").toString() + " wp ");
if (wp.get("name").toString().toLowerCase().contains(s)) {
fdata.add(wp);
}
}
}
else {
fdata = new ArrayList<>(selecteddata);
}
notifyDataSetChanged();
}
public class Holder
{
ImageView g_img;
ImageView plus;
ImageView mines;
TextView g_name;
TextView g_price;
TextView g_off;
TextView count;
TextView f_range;
TextView sum;
TextView temp2;
}
#Override
public int getCount() {
return fdata.size();
}
#Override
public HashMap<String, Object> getItem(int i) {
return fdata.get(i);
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Typeface font_titr = Typeface.createFromAsset(context.getAssets(), "fonts/titr.TTF");
final HashMap<String, Object> hm = fdata.get(position);
if (convertView == null ) {
holder = new Holder();
convertView = LayoutInflater.from(context).
inflate(R.layout.my_row_layout2, parent, false);
holder.g_img = (ImageView) convertView.findViewById(R.id.f_img);
holder.g_name = (TextView) convertView.findViewById(R.id.f_name);
holder.g_price = (TextView) convertView.findViewById(R.id.f_price);
holder.g_off = (TextView) convertView.findViewById(R.id.f_off);
holder.count = (TextView) convertView.findViewById(R.id.f_count);
holder.f_range = (TextView) convertView.findViewById(R.id.f_kilo);
holder.plus = (ImageView) convertView.findViewById(R.id.plus_id_btn);
holder.mines = (ImageView) convertView.findViewById(R.id.mines_id_btn);
holder.sum = (TextView) convertView.findViewById(R.id.count_sum_id);
holder.temp2 = (TextView) convertView.findViewById(R.id.txt2);
//Date currentTime = Calendar.getInstance().getTime();
convertView.setTag(holder);
// Log.i("mosi",convertView.getTag() + " tagfffff " + hm.get("convertview"));
hm.put("convertview", "1");
}
else
{
holder = (Holder) convertView.getTag();
// Log.i("mosi",convertView.getTag() + " tag " + hm.get("convertview"));
}
final View tempview = convertView;
// set font++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
holder.g_price.setTypeface(font_titr, Typeface.NORMAL);
holder.g_name.setTypeface(font_titr, Typeface.BOLD);
holder.g_off.setTypeface(font_titr, Typeface.NORMAL);
holder.count.setTypeface(font_titr, Typeface.NORMAL);
holder.sum.setTypeface(font_titr, Typeface.NORMAL);
holder.temp2.setTypeface(font_titr, Typeface.NORMAL);
//----------------------------------------------------------------------------------------
// Set pre count and sum
holder.sum.setText(" میلغ کل : " + hm.get("sum").toString() + " تومان ");
holder.count.setText(hm.get("count").toString());
final String oldprice = hm.get("price").toString();
holder.g_off.setText(hm.get("off").toString());
holder.g_name.setText(hm.get("disc").toString());
holder.f_range.setText(hm.get("f_range").toString());
final float f=
(Float.valueOf(oldprice)*
Float.valueOf(holder.g_off.getText().toString()))/100;
// holder.g_price.setText(" قیمت : "+ DtoS((Float.valueOf(oldprice.toString()))-f)+" تومان ");
holder.g_price.setText(" قیمت : "+ oldprice +" تومان ");
File imageFile = new File(hm.get("image").toString());
if(imageFile.exists()){
holder.g_img.setImageBitmap(BitmapFactory.decodeFile(imageFile.getAbsolutePath()));
}
else
holder.g_img.setImageResource(R.drawable.coming_soon);
holder.plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
change_count(holder, hm, "p", tempview, ChangeType.DtoS((Float.valueOf(oldprice.toString())) - f), position);
}
});
holder.mines.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
change_count(holder, hm, "m", tempview , ChangeType.DtoS((Float.valueOf(oldprice.toString()))-f), position);
}
});
// Button Pay && More
pay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (BuyList.size() > 0) {
Intent intent = new Intent(context, Payment_act.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("data", BuyList);
intent.putExtra("all_data", data);
intent.putExtra("mobile", user_mobile);
view.getContext().startActivity(intent);
//
} else {
Toast.makeText(context, "سبد خرید شما خالی است", Toast.LENGTH_LONG).show();
}
}
});
more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, Choose_act.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("blist", BuyList);
intent.putExtra("data", data);
intent.putExtra("mobile", user_mobile);
view.getContext().startActivity(intent);
// ((Activity)context).finish();
}
});
// Search -------------------------------------------------------------------
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence s, int i, int i1, int i2) {
// Log.i("mosi", s+" --- s ***");
// filter(s.toString(), holder.g_img);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
return convertView;
}
// template
// Onclick for mines and plus Button
//#Override
public void change_count(final Holder holder1, HashMap<String, Object> hm_addtolist, String tag, View c_view, String oldprice, int position) {
// Log.i("mosi", position+" position on list ");
String is_pack = hm_addtolist.get("is_pack").toString();
ChangeType ch = new ChangeType();
double temp1 = 0;
double p_with_off = 0;
holder = (Holder) c_view.getTag();
String off = hm_addtolist.get("off").toString();
String num_sum = "0";
if (ch.stringToDouble(off)>0)
{
p_with_off = ch.stringToDouble(hm_addtolist.get("price_with_off").toString());
}
else
p_with_off = ch.stringToDouble(oldprice.toString());
holder.count= (TextView) c_view.findViewById(R.id.f_count);
holder.sum = (TextView) c_view.findViewById(R.id.count_sum_id);
if (!holder.count.getText().toString().equals("") && holder.count!= null)
temp1 = ch.stringToDouble(holder.count.getText().toString());
//my_alert("", temp1+"");
if (tag.equals("p")) {
if (is_pack.equals("1"))
temp1 = temp1 + 1;
else
temp1 = temp1 + 0.5;
// Log.i("mosi", " ::: set 2 !!!!");
holder.count.setText(DtoS(temp1));
num_sum = String.format("%d", (long)(temp1 * p_with_off));
holder.sum.setText(" میلغ کل : " + num_sum + " تومان ");
} else if (tag.equals("m")) {
if (is_pack.equals("1")) {
if (temp1 > 1) {
temp1 = (temp1 - 1);
holder.count.setText(DtoS(temp1));
num_sum = String.format("%d", (long) (temp1 * p_with_off));
holder.sum.setText(" میلغ کل : " + num_sum + " تومان ");
} else {
holder.count.setText("0");
holder.sum.setText("مبلغ کل : 0 تومان");
num_sum = "0";
BuyList.remove(hm_addtolist);
notifyDataSetChanged();
buy_toolbar_count.setText(String.valueOf(BuyList.size()));
}
}
else {
if (temp1 > 0.5) {
temp1 = (temp1 - 0.5);
holder.count.setText(DtoS(temp1));
num_sum = String.format("%d", (long) (temp1 * p_with_off));
holder.sum.setText(" میلغ کل : " + num_sum + " تومان ");
} else {
holder.count.setText("0");
holder.sum.setText("مبلغ کل : 0 تومان");
num_sum = "0";
hm_addtolist.put("count","0");
hm_addtolist.put("sum","0");
BuyList.remove(hm_addtolist);
notifyDataSetChanged();
buy_toolbar_count.setText(String.valueOf(BuyList.size()));
}
}
}
//}
if (!num_sum.equals("0")) {
hm_addtolist.put("sum", num_sum);
hm_addtolist.put("count", holder.count.getText().toString());
boolean check = false;
for (int i = 0; i < BuyList.size(); i++) {
if (BuyList.get(i).get("name").toString().equals(hm_addtolist.get("name").toString())) {
check = true;
HashMap<String, Object> temp_updatelist = BuyList.get(i);
temp_updatelist.put("sum", num_sum);
temp_updatelist.put("count", holder.count.getText().toString());
// BuyList.add(temp_updatelist);
// Log.i("mosi", "add count "+i+"");
// Toast.makeText(context, "ok", Toast.LENGTH_SHORT);
notifyDataSetChanged();
}
}
if (!check) {
// Log.i("mosi", "add count to :: "+hm_addtolist.get("name")+"");
BuyList.add(hm_addtolist);
buy_toolbar_count.setText(String.valueOf(BuyList.size()));
notifyDataSetChanged();
}
}
notifyDataSetChanged();
// Log.i("mosi", BuyList.toString());
// clearbug( c_view);
}
}
make list on activity
I have a listview that when I change the value of one item (count) with click on plus button, Everything is fine as long as the user do scroll down and show more items
And we see that on each page of the scroll has changed a value of item!!!
idont kNow why everything seems fine!!
private void setlist() {
ArrayList<HashMap<String, Object>> selected_data = new ArrayList<>();
for (int i = 0; i < all_data.size(); i++) {
if (all_data.get(i).get("type").toString().equals(mtag)) {
HashMap<String, Object> t = all_data.get(i);
selected_data.add(t);
}
}
//Log.i("mosi",selected_data.toString());
EditText search = (EditText) findViewById(R.id.et_search_id);
ImageView pay = (ImageView) findViewById(R.id.btn_pay_firstpage);
ImageView more = (ImageView) findViewById(R.id.btn_more_firstpage);
String[] from = {"image", "name", "price", "off"};
int[] to = {R.id.f_img, R.id.f_name, R.id.f_price, R.id.f_off};
final MyAdapter adb = new MyAdapter(getBaseContext(), all_data, selected_data, from, to, BuyList, pay, more, user_mobile, buyCount_toolbar, search);
lv.setAdapter(adb);
}
I have a listview that when I change the value of one item (count) with click on plus button, Everything is fine as long as the user do scroll down and show more items
And we see that on each page of the scroll has changed a value of item!!!
idont kNow why everything seems fine!!
its my activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="rtl"
android:background="#drawable/main_background_theme">
<include
android:id="#+id/mytoolbar"
layout="#layout/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"/>
<include
android:id="#+id/app_message"
layout="#layout/message"
android:layout_height="30dp"
android:layout_width="match_parent"
android:layout_below="#+id/mytoolbar"/>
<include
android:id="#+id/searchbox_id"
layout="#layout/searchbox"
android:layout_height="40sp"
android:layout_width="match_parent"
android:layout_below="#+id/app_message"
android:visibility="invisible"/>
<android.support.v4.widget.DrawerLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/searchbox_id"
android:id="#+id/FirstPage_id">
<RelativeLayout
android:id="#+id/rv_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainLayoutActivity">
<ListView
android:id="#+id/my_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/listDivader"
android:dividerHeight="1dp"
android:paddingBottom="?attr/actionBarSize" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignBottom="#id/my_listview"
android:background="#color/toolbar_back"
android:orientation="horizontal">
<ImageView
android:id="#+id/btn_pay_firstpage"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="50"
android:paddingLeft="10sp"
android:src="#drawable/btn_pay" />
<ImageView
android:id="#+id/btn_more_firstpage"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="50"
android:paddingLeft="10sp"
android:src="#drawable/btn_more" />
</LinearLayout>
</RelativeLayout>
<fragment
android:layout_width="180dp"
android:layout_height="match_parent"
android:id="#+id/drawer_fragment"
android:layout_gravity="start"
android:layout="#layout/drawer_fragment_layout"
tools:layout="#layout/drawer_fragment_layout"
android:name="com.com.seyedi89gmail.sm.zanco.Drawer_fragment">
</fragment>
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
Remove notifyDataSetChanged from if-else conditions, May this will work
public void filter(String s, ImageView img) {
HashMap<String, Object> wp = new HashMap<>();
if (!s.equals("")) {
fdata.clear();
for (int i = 0 ;i<data.size();i++) {
wp = data.get(i);
if (wp.get("name").toString().toLowerCase().contains(s)) {
fdata.add(wp);
//notifyDataSetChanged();
}
}
}
else {
fdata = new ArrayList<>(selecteddata);
//notifyDataSetChanged();
}
notifyDataSetChanged();
}
you can use NestedScrollview outside the listview and stop the scrolling of listview by using this: smoothScrollBy(0, 0);
More than one value is received but when I am parsing the JSON into Android, it is only showing the first value.
Here is the JsonNew.php file:
require "index.php";
$user_shopID = $_POST["UniqueKey"] ;
$sql_query="Select * from products where ShopID like '$user_shopID';";
$result = mysqli_query($con, $sql_query);
$response = array();
while ($row = mysqli_fetch_array($result))
{
array_push($response,array("ProductID"=>$row[0],"Product Name"=>$row[1], "Buying Price"=>$row[3], "Selling Price"=>$row[4]));
}
echo json_encode(array("server_response"=>$response));
mysqli_close($con);
This is the ContactAdapters.java:
public class ContactAdapter extends ArrayAdapter {
List list = new ArrayList();
public ContactAdapter(#NonNull Context context, #LayoutRes int resource) {
super(context, resource);
}
public void add(Contacts object) {
super.add(object);
list.add(object);
}
#Override
public int getCount() {
return list.size();
}
#Nullable
#Override
public Object getItem(int position) {
return list.get(position);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View row;
row = convertView;
ContactHolder contactHolder;
if (row == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.row_layout, parent, false);
contactHolder = new ContactHolder();
contactHolder.tx_id = (TextView) row.findViewById(R.id.id);
contactHolder.tx_name = (TextView) row.findViewById(R.id.name);
contactHolder.tx_buy = (TextView) row.findViewById(R.id.buy);
contactHolder.tx_sell = (TextView) row.findViewById(R.id.sell);
row.setTag(contactHolder);
} else {
contactHolder = (ContactHolder) row.getTag();
}
Contacts contacts = (Contacts) this.getItem(position);
contactHolder.tx_id.setText(contacts.getId());
contactHolder.tx_name.setText(contacts.getName());
contactHolder.tx_buy.setText(contacts.getBuy());
contactHolder.tx_sell.setText(contacts.getSell());
return row;
}
static class ContactHolder {
TextView tx_id, tx_name, tx_buy, tx_sell;
}
}
And this the row_layout.xml
android:layout_width="match_parent"
android:layout_height="75dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/id"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:text="TextView"
android:gravity="center"
android:textColor="#000000"
android:layout_below="#+id/textView13" />
<TextView
android:id="#+id/name"
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/id"
android:text="TextView"
android:gravity="center"
android:textColor="#000000"
android:layout_below="#+id/textView14" />
<TextView
android:id="#+id/buy"
android:layout_width="100dp"
android:layout_height="match_parent"
android:text="TextView"
android:gravity="center"
android:textColor="#000000"
android:layout_toRightOf="#+id/name"
android:layout_toEndOf="#+id/name"
android:layout_alignTop="#+id/name" />
<TextView
android:id="#+id/sell"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/buy"
android:text="TextView"
android:gravity="center"
android:textColor="#000000"
android:layout_alignTop="#+id/buy"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
Here is DisplayProductsListview.java
listview = (ListView) findViewById(R.id.listview);
contactAdapter = new ContactAdapter(this,R.layout.row_layout);
listview.setAdapter(contactAdapter);
json_string = getIntent().getExtras().getString("json_data");
try {
jsonObject = new JSONObject(json_string);
jsonArray = jsonObject.getJSONArray("server_response");
int count=0;
String id, name, buy, sell;
while (count<jsonObject.length()){
JSONObject JO = jsonArray.getJSONObject(count);
id = JO.getString("ProductID");
name = JO.getString("Product Name");
buy = JO.getString("Buying Price");
sell = JO.getString("Selling Price");
Contacts contacts = new Contacts(id,name,buy,sell);
contactAdapter.add(contacts);
count++;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Here is the Contacts.java
private String id, name, buy, sell;
public Contacts(String id, String name, String buy, String sell){
this.setId(id);
this.setName(name);
this.setBuy(buy);
this.setSell(sell);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBuy() {
return buy;
}
public void setBuy(String buy) {
this.buy = buy;
}
public String getSell() {
return sell;
}
public void setSell(String sell) {
this.sell = sell;
}
}
When I am getting the JSON datas from the server, they are coming perfectly, but when I am making them display in a list view those datas are not coming. Only the first data and his values are coming into the list view.
Here are the Screenshots:
Here you will See what is actually happening with me
In the contactAdapter class you have to create a ArrayList.
ArrayList<Contact> arrayList = new ArrayList<>();
Somewhat you have to do like this.
change this function
while (count<jsonArray.length()){
JSONObject JO = jsonArray.getJSONObject(count);
id = JO.getString("ProductID");
name = JO.getString("Product Name");
buy = JO.getString("Buying Price");
sell = JO.getString("Selling Price");
Contacts contacts = new Contacts(id,name,buy,sell);
contactAdapter.add(contacts);
count++;
}
you have to use jsonarray length not the object length.
Good day guys,
I successfully populated my custom-listview-layout in my activity,
but the problem is I can't get all the value of populated EditText in my listview, please help me what approach should I do,
thanks
Picture Adapter.java
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
final dataHandler handler;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate( R.layout.row_layout,parent, false);
handler = new dataHandler();
handler.pictures = (ImageView) row.findViewById(R.id.pictures);
handler.name = (TextView) row.findViewById(R.id.picturename);
handler.price= (EditText) row.findViewById(R.id.price);
handler.add = (Button) row.findViewById(R.id.btnplus);
handler.minus = (Button) row.findViewById(R.id.btnminus);
row.setTag(handler);
}else{
handler = (dataHandler) row.getTag();
}
PSP psp;
psp =(PSP) this.getItem(position);
Picasso.with(getContext()).load(psp.getPicture()).resize(200, 155).into(handler.pictures);
handler.name.setText(psp.getName());
handler.price.setText(psp.getPrice());
return row;
}
MainActivity.java
PictureAdapter adapter;
listView = (ListView) findViewById(R.id.ls);
adapter = new PictureAdapter(this,R.layout.row_layout);
listView.setAdapter(adapter);
try {
JSONArray users = response.getJSONArray("user");
for (int x = 0; x <= users.length()-1; x++) {
JSONObject user = users.getJSONObject(x);
PSP psp = new PSP(imageUri+user.getString("image")+".png",user.getString("username"),"0");
adapter.add(psp);
}
} catch (JSONException e) {
e.printStackTrace();
}
PSP.java
public class PSP
{
private String picture;
private String name;
private String price;
public String getPicture() {
return picture;
}
public PSP(String picture, String name, String price){
this.setPicture(picture);
this.setName(name);
this.setPrice(price);
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
row_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="80dp"
android:background="#000000">
<ImageView
android:id="#+id/pictures"
android:layout_width="100dp"
android:layout_height="75dp"
android:layout_alignParentLeft="true"
/>
<TextView
android:id="#+id/picturename"
android:layout_width="115dp"
android:layout_height="75dp"
android:layout_toRightOf="#+id/pictures"
android:text="Kim Domingo"
android:gravity="center"
android:textColor="#FFFFFF"
/>
<Button
android:id="#+id/btnplus"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:text="+"
android:textSize="50px"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/picturename"
android:layout_toEndOf="#+id/picturename"
/>
<EditText
android:id="#+id/price"
android:layout_width="50dp"
android:layout_height="50dp"
android:focusable="false"
android:textColor="#FFFFFF"
android:inputType="number"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/btnplus"
android:layout_toEndOf="#+id/btnplus" />
<Button
android:id="#+id/btnminus"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:text="-"
android:textSize="50px"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/price"
android:layout_toEndOf="#+id/price" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#FFFFFF"
android:layout_below="#+id/pictures"
android:id="#+id/editText"></View>
I created same before like this
You can use the HashMap map = new HashMap<>(); for what item user click. I assume that you use two button click are available in adapter class if not then add it.
Step 1 First Declare the HashMap map = new HashMap<>(); in adapter.
Step 2 Then put value in HashMap map.put("key","value"); This code put in both plus and minus button click event.
Step 3 Call ShowHashMapValue(); method below to the map.put("key","value"); for see the HashMap values check logcat for that.
Compare this adapter code for understand easily if any problem just comment below.
ListAdapter.java
public class ListAdapter extends BaseAdapter {
public ArrayList<Integer> quantity = new ArrayList<Integer>();
public ArrayList<Integer> price = new ArrayList<Integer>();
private String[] listViewItems, prices, static_price;
TypedArray images;
View row = null;
static String get_price, get_quntity;
int g_quntity, g_price, g_minus;
private Context context;
CustomButtonListener customButtonListener;
static HashMap<String, String> map = new HashMap<>();
public ListAdapter(Context context, String[] listViewItems, TypedArray images, String[] prices) {
this.context = context;
this.listViewItems = listViewItems;
this.images = images;
this.prices = prices;
for (int i = 0; i < listViewItems.length; i++) {
quantity.add(0);
}
}
public void setCustomButtonListener(CustomButtonListener customButtonListner) {
this.customButtonListener = customButtonListner;
}
#Override
public int getCount() {
return listViewItems.length;
}
#Override
public String getItem(int position) {
return listViewItems[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ListViewHolder listViewHolder;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.activity_custom_listview, parent, false);
listViewHolder = new ListViewHolder();
listViewHolder.tvProductName = (TextView) row.findViewById(R.id.tvProductName);
listViewHolder.ivProduct = (ImageView) row.findViewById(R.id.ivproduct);
listViewHolder.tvPrices = (TextView) row.findViewById(R.id.tvProductPrice);
listViewHolder.btnPlus = (ImageButton) row.findViewById(R.id.ib_addnew);
listViewHolder.edTextQuantity = (EditText) row.findViewById(R.id.editTextQuantity);
listViewHolder.btnMinus = (ImageButton) row.findViewById(R.id.ib_remove);
static_price = context.getResources().getStringArray(R.array.Price);
row.setTag(listViewHolder);
} else {
row = convertView;
listViewHolder = (ListViewHolder) convertView.getTag();
}
listViewHolder.ivProduct.setImageResource(images.getResourceId(position, -1));
listViewHolder.edTextQuantity.setText(quantity.get(position) + "");
listViewHolder.tvProductName.setText(listViewItems[position]);
listViewHolder.tvPrices.setText(prices[position]);
listViewHolder.btnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (customButtonListener != null) {
customButtonListener.onButtonClickListener(position, listViewHolder.edTextQuantity, 1);
quantity.set(position, quantity.get(position) + 1);
//price.set(position, price.get(position) + 1);
row.getTag(position);
get_price = listViewHolder.tvPrices.getText().toString();
g_price = Integer.valueOf(static_price[position]);
get_quntity = listViewHolder.edTextQuantity.getText().toString();
g_quntity = Integer.valueOf(get_quntity);
map.put("" + listViewHolder.tvProductName.getText().toString(), " " + listViewHolder.edTextQuantity.getText().toString());
// Log.d("A ", "" + a);
// Toast.makeText(context, "A" + a, Toast.LENGTH_LONG).show();
// Log.d("Position ", "" + position);
// System.out.println(+position + " Values " + map.values());
listViewHolder.tvPrices.getTag();
listViewHolder.tvPrices.setText("" + g_price * g_quntity);
ShowHashMapValue();
}
}
});
listViewHolder.btnMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (customButtonListener != null) {
customButtonListener.onButtonClickListener(position, listViewHolder.edTextQuantity, -1);
if (quantity.get(position) > 0)
quantity.set(position, quantity.get(position) - 1);
get_price = listViewHolder.tvPrices.getText().toString();
g_minus = Integer.valueOf(get_price);
g_price = Integer.valueOf(static_price[position]);
int minus = g_minus - g_price;
if (minus >= g_price) {
listViewHolder.tvPrices.setText("" + minus);
}
map.put("" + listViewHolder.tvProductName.getText().toString(), " " + listViewHolder.edTextQuantity.getText().toString());
ShowHashMapValue();
}
}
});
return row;
}
private void ShowHashMapValue() {
/**
* get the Set Of keys from HashMap
*/
Set setOfKeys = map.keySet();
/**
* get the Iterator instance from Set
*/
Iterator iterator = setOfKeys.iterator();
/**
* Loop the iterator until we reach the last element of the HashMap
*/
while (iterator.hasNext()) {
/**
* next() method returns the next key from Iterator instance.
* return type of next() method is Object so we need to do DownCasting to String
*/
String key = (String) iterator.next();
/**
* once we know the 'key', we can get the value from the HashMap
* by calling get() method
*/
String value = map.get(key);
System.out.println("Key: " + key + ", Value: " + value);
}
}
}
So so here is logic. You need to declare a boolean in PSP. by default set it to false.
Now when + button will be triggered you need to set that boolean check to true
then in your set price create this logic.
public String getPrice() {
if(check==true){
price++;
}
else{
price--;
}
return price;
}
If i correctly understand you then this surely will help you. Good Luck!
I'm making a minesweeper game. I'm placing all of the buttons I use for the game in a GridLayout.
The buttons eventually push the layout to be bigger than the size of the screen, so I placed the layout in a HorizontalScrollView and a ScrollView. However, when the game ends, I want to zoom out the layout so I can see all of the buttons on screen.
I've posted the relevant files, although the most important content is fragment_grid.xml (the xml file containing the GridLayout) and GridFragment::gameOver() (where I want to put the zoom-out code)
fragment_grid.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scrollbars="none"
android:overScrollMode="never">
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grid"
android:columnCount="10"
android:rowCount="10">
</GridLayout>
</HorizontalScrollView>
</ScrollView>
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:clickable="true"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</RelativeLayout>
GridFragment.java:
public class GridFragment extends Fragment {
GridLayout gridLayout;
public enum GameState{READY, PLAYING, WIN, LOSE}
GameState gameState;
public GridFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
gameState = GameState.READY;
View view = inflater.inflate(R.layout.fragment_grid, container, false);
gridLayout = (GridLayout)view.findViewById(R.id.grid);
MButton[] buttons = generateGrid(100,25);
for(MButton mButton:buttons){
gridLayout.addView(mButton);
}
return view;
}
public MButton[] generateGrid(int gridSize, int numMines){
Log.d("gridSize",""+gridSize);
Log.d("numMines",""+numMines);
ArrayList<Integer> array = new ArrayList<Integer>();
for (int i = 0; i < gridSize; i++) {
array.add(new Integer(i));
}
Log.d("unsorted",array.toString());
Collections.shuffle(array,new Random(System.currentTimeMillis()));
MButton[] mButtons = new MButton[gridSize];
MButton mButton;
String numList = array.toString();
Log.d("arraySize",""+array.size());
Log.d("array",numList);
for (int i = 0; i < gridSize; i++) {
int x = array.get(i);
mButton = new MButton(getActivity(),i, numMines > x);
mButtons[i] = mButton;
}
return generateMineCount(mButtons);
}
private MButton[] generateMineCount(MButton[] mButtons){
int rows = gridLayout.getRowCount();
int columns = gridLayout.getColumnCount();
for (int i = 0; i < mButtons.length; i++) {
if((i/columns) > 0){if(mButtons[i-columns].isMine()){mButtons[i].addAdjacentMines();}}
if((i/columns) < rows-1){if(mButtons[i+columns].isMine()){mButtons[i].addAdjacentMines();}}
if((i%rows) > 0){if(mButtons[i-1].isMine()){mButtons[i].addAdjacentMines();}}
if((i%rows) < columns-1){if(mButtons[i+1].isMine()){mButtons[i].addAdjacentMines();}}
if( ((i/columns) > 0)&&((i%rows) > 0) ){if(mButtons[i-columns-1].isMine()){mButtons[i].addAdjacentMines();}}
if( ((i/columns) < rows-1)&&((i%rows) > 0) ){if(mButtons[i+columns-1].isMine()){mButtons[i].addAdjacentMines();}}
if( ((i/columns) > 0)&&((i%rows) < columns-1) ){if(mButtons[i-columns+1].isMine()){mButtons[i].addAdjacentMines();}}
if( ((i/columns) < rows-1)&&((i%rows) < columns-1) ){if(mButtons[i+columns+1].isMine()){mButtons[i].addAdjacentMines();}}
if(!mButtons[i].isMine() && mButtons[i].getAdjacentMines() > 0){mButtons[i].displayMines();}
}
return mButtons;
}
public void startGame(){
gameState = GameState.PLAYING;
}
public void gameOver(){
gameState = GameState.LOSE;
for (int i = 0; i < gridLayout.getChildCount(); i++) {
MButton mb = (MButton)gridLayout.getChildAt(i);
mb.setOnTouchListener(null);
//insert zoom-out layout code here
}
gridLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
MButton.java:
public class MButton extends Button {
public enum State{NORMAL, OPENED, FLAGGED, UNKNOWN}
State state;
boolean longPress;
long startTime = 0;
int num;
boolean mine;
final float scale = getContext().getResources().getDisplayMetrics().density;
int adjacentMines = 0;
MainActivity mainActivity = (MainActivity)getContext();
GridFragment gridFragment = (GridFragment)mainActivity.getFragmentManager().findFragmentByTag("gridFragment");
ImageButton startButton = (ImageButton)(mainActivity.getActionBar()).getCustomView().findViewById(R.id.actionBarLogo);
static Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long milliseconds = System.currentTimeMillis() - startTime;
longPress = false;
if(milliseconds >= 1500) {
longPressTile();
timerHandler.removeCallbacks(timerRunnable);
}
else
timerHandler.postDelayed(this, 0);
}
};
public MButton(Context context, int i, boolean m) {
super(context);
create(i, m);
}
public MButton(Context context, AttributeSet attrs, int i, boolean m) {
super(context, attrs);
create(i, m);
}
public MButton(Context context, AttributeSet attrs, int defStyleAttr, int i, boolean m) {
super(context, attrs, defStyleAttr);
create(i, m);
}
private void longPressTile(){
longPress = true;
setBackgroundResource(R.drawable.tile);
startButton.setImageResource(R.drawable.smiley);
if(state == State.FLAGGED || state == State.UNKNOWN){
state = State.NORMAL;
setText("");
}
else if(state == State.NORMAL){
state = State.FLAGGED;
setText("F");
}
}
private boolean isInGrayArea(float xCoord, float yCoord){
int xValue = (int) ((xCoord/scale)+0.5);
int yValue = (int) ((yCoord/scale)+0.5);
Log.d("button"+num,"("+xValue+","+yValue+")");
Log.d("size","("+Integer.toString(getWidth())+","+Integer.toString(getHeight())+")");
return (xValue >= 5)&&(xValue < 45)&&(yValue >= 5)&&(yValue < 45);
}
public void addAdjacentMines(){
adjacentMines++;
}
public boolean isMine(){
return mine;
}
public void displayMines(){
if(mine)
setText("M");
else if(hasAdjacentMines())
setText(""+adjacentMines);
else
setText("");
}
public int getAdjacentMines(){
return adjacentMines;
}
public boolean hasAdjacentMines(){ return getAdjacentMines() > 0;}
private void openAdjacentButtons(){
GridLayout gridLayout = gridFragment.gridLayout;
int rows = gridLayout.getRowCount();
int columns = gridLayout.getColumnCount();
if((num/columns) > 0){((MButton)gridLayout.getChildAt(num-columns)).revealButton();}
if((num/columns) < rows-1){((MButton)gridLayout.getChildAt(num+columns)).revealButton();}
if((num%rows) > 0){((MButton)gridLayout.getChildAt(num-1)).revealButton();}
if((num%rows) < columns-1){((MButton)gridLayout.getChildAt(num+1)).revealButton();}//
if( ((num/columns) > 0)&&((num%rows) > 0) ){((MButton)gridLayout.getChildAt(num-columns-1)).revealButton();}
if( ((num/columns) < rows-1)&&((num%rows) > 0) ){((MButton)gridLayout.getChildAt(num+columns-1)).revealButton();}
if( ((num/columns) > 0)&&((num%rows) < columns-1) ){((MButton)gridLayout.getChildAt(num-columns+1)).revealButton();}
if( ((num/columns) < rows-1)&&((num%rows) < columns-1) ){((MButton)gridLayout.getChildAt(num+columns+1)).revealButton();}
}
public void revealButton() {
if (state != State.OPENED){
state = State.OPENED;
displayMines();
if (!isMine() && !hasAdjacentMines())
openAdjacentButtons();
else if(isMine()){
startButton.setImageResource(R.drawable.smiley3);
gridFragment.gameOver();
}
setBackgroundResource(R.drawable.tile3);
}
}
private void create(int i, boolean m){
state = State.NORMAL;
num = i;
mine = m;
setBackgroundResource(R.drawable.tile);
setLayoutParams(new LinearLayout.LayoutParams(150,150));
if(mine){
setText("m");
}
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent me) {
if(isInGrayArea(me.getX(), me.getY())){
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (state != State.OPENED) {
if(gridFragment.gameState == GridFragment.GameState.READY)
gridFragment.startGame();
startTime = System.currentTimeMillis();
v.setBackgroundResource(R.drawable.tile2);
startButton.setImageResource(R.drawable.smiley2);
timerHandler.postDelayed(timerRunnable, 0);
}
return true;
}
case MotionEvent.ACTION_UP: {
if (!longPress) {
startButton.setImageResource(R.drawable.smiley);
switch(state){
case NORMAL:{
revealButton();
break;
}
case UNKNOWN:{
state = State.UNKNOWN;
v.setBackgroundResource(R.drawable.tile);
setText("?");
break;
}
case FLAGGED:{
state = State.FLAGGED;
v.setBackgroundResource(R.drawable.tile);
setText("F");
}
}
}
timerHandler.removeCallbacks(timerRunnable);
return true;
}
}
}
return false;
}
});
}
}
MainActivity.java
public class MainActivity extends Activity {
private boolean mInit = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionBar = getActionBar();
actionBar.setCustomView(R.layout.actionbar);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/digital-7.ttf");
TextView myTextView = (TextView)findViewById(R.id.textView1);
TextView myTopTextView = (TextView)findViewById(R.id.topTextView1);
myTextView.setTypeface(myTypeface);
myTopTextView.setTypeface(myTypeface);
if (findViewById(R.id.fragment_container) != null){
if (savedInstanceState != null) {
return;
}
}
}
private void initial(){
GridFragment gFragment = new GridFragment();
gFragment.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.fragment_container, gFragment,"gridFragment").commit();
}
#Override
protected void onStart() {
if (!mInit) {
mInit = true;
initial();
}
super.onStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
P.S. Happy New Year's!
i guess this would help: Android - zoom in/out RelativeLayout with spread/pinch
you can applay the same implementation for gridLayout good luck :) and Happy new year
I know its been 6 months I spent hours trying to make this work.
This class should work for any view or viewgroup. Just extend whatever view or viewgroup needs to zoom.
https://github.com/Xjasz/AndroidZoomableViewGroup
I'm using UIL to load thrumbs in a listview.
here is the imageview and the spinner in the cell layout :
<ImageView
android:id="#+id/imgAlbum"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_gravity="center|left"
android:scaleType="centerCrop"
android:visibility="gone" />
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
The list :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background"
android:orientation="vertical" >
<ListView
android:id="#+id/list_restaurant"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp" >
</ListView>
</LinearLayout>
I config the loader like that :
public void setImageLoader(ImageLoader imageLoader, Context context) {
File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration _config;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
_config = new ImageLoaderConfiguration.Builder(context).memoryCacheExtraOptions(0, 0).discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75).taskExecutor(null)
.taskExecutorForCachedImages(null).threadPoolSize(3) // default
.threadPriority(Thread.NORM_PRIORITY - 1) // default
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.denyCacheImageMultipleSizesInMemory().memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // default
.memoryCacheSize(2 * 1024 * 1024).discCache(new UnlimitedDiscCache(cacheDir)) // default
.discCacheSize(50 * 1024 * 1024).discCacheFileCount(100).discCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
.imageDownloader(new BaseImageDownloader(context)) // default
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
.enableLogging().build();
}
else {
_config = new ImageLoaderConfiguration.Builder(context).memoryCacheExtraOptions(0, 0)
// default/screendimensions
.discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75).taskExecutor(AsyncTask.THREAD_POOL_EXECUTOR).taskExecutorForCachedImages(AsyncTask.THREAD_POOL_EXECUTOR)
.threadPoolSize(3) // default
.threadPriority(Thread.NORM_PRIORITY - 1) // default
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.denyCacheImageMultipleSizesInMemory().memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // default
.memoryCacheSize(2 * 1024 * 1024).discCache(new UnlimitedDiscCache(cacheDir)) // default
.discCacheSize(50 * 1024 * 1024).discCacheFileCount(100).discCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
.imageDownloader(new BaseImageDownloader(context)) // default
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
.enableLogging().build();
}
if (!imageLoader.isInited()) {
imageLoader.init(_config);
}
}
And in the baseadapter i use it like that :
private ImageLoader _imageLoader;
private DisplayImageOptions _options;
in the constructor
this._imageLoader = ImageLoader.getInstance();
this._options = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.error).showImageOnFail(R.drawable.error).cacheInMemory().cacheOnDisc().bitmapConfig(Bitmap.Config.RGB_565)
.build();
Utils utils = new Utils();
utils.setImageLoader(_imageLoader, _activity);
In the GetView() :
final ProgressBar spinner = (ProgressBar) convertView.findViewById(R.id.loading);
_imageLoader.displayImage(etablissement.getImgThumb(), cellHolder.imageIcon, _options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
view.setVisibility(View.GONE);
spinner.setVisibility(View.VISIBLE);
spinner.invalidate();
view.invalidate();
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason.getType()) {
case IO_ERROR:
message = "Input/Output error";
break;
case DECODING_ERROR:
message = "Image can't be decoded";
break;
case NETWORK_DENIED:
message = "Downloads are denied";
break;
case OUT_OF_MEMORY:
message = "Out Of Memory error";
break;
case UNKNOWN:
message = "Unknown error";
break;
}
view.setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);spinner.invalidate();
view.invalidate();
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
view.setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
spinner.invalidate();
view.invalidate();
}
});
Everything works fine BUT the spinner stay instead of the imageview until you scroll the list the redraw the cells.. The imageview should refresh itself when the image is downloaded/got from cache or invalidate()
Here the list loading stay like that : http://imagik.fr/view-rl/45673
Here when i scroll down the imageview refresh : http://imagik.fr/view-rl/45674
Here when i re-scoll up the imageview refresh : http://imagik.fr/view-rl/45675
Any idea ??
EDIT:
The full adapter code (with the UIL part inside) :
public class AdapterDirectories extends BaseAdapter {
/**
* PRIVATE ATTRIBUTES
*/
// LOG
private static final String TAG = AdapterDirectories.class.getSimpleName();
// IHM
private static LayoutInflater _inflater = null;
private Activity _activity;
// DATA
private DataManager _dataManager;
private ImageLoader _imageLoader;
private DisplayImageOptions _options;
private int _section;
private float _latitude;
private float _longitude;
private List<Contact> _listContacts = new ArrayList<Contact>();
private List<Favoris> _listFavoris = new ArrayList<Favoris>();
public AdapterDirectories(Activity activity, boolean favoris, float latitude, float longitude, int section) {
this._activity = activity;
this._latitude = latitude;
this._longitude = longitude;
this._section = section;
//
ContactRepository contactRep = null;
//
if (favoris == false) {
_listContacts = EtablissementApplication._dataManager.get_listOfContacts(_section, _activity);
}
else {
// FAVORITE
this._listFavoris = EtablissementApplication._dataManager.get_listOfFavoris();
// DATA
contactRep = new ContactRepository(_activity);
contactRep.Open();
for (Favoris unFavoris : _listFavoris) {
_listContacts.add(contactRep.GetById(unFavoris.getIdentifiantContact()));
}
contactRep.Close();
}
_inflater = (LayoutInflater) _activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this._imageLoader = ImageLoader.getInstance();
this._options = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.error).showImageOnFail(R.drawable.error).cacheInMemory().cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(Utils.IMAGE_BORDER_RADIUS)).bitmapConfig(Bitmap.Config.RGB_565).build();
Utils utils = new Utils();
utils.setImageLoader(_imageLoader, _activity);
}
#Override
public int getCount() {
return _listContacts.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
CellHolder cellHolder = null;
Contact _contact = _listContacts.get(position);
Etablissement etablissement = new Etablissement();
//
// GET
if (convertView == null) {
view = _inflater.inflate(R.layout.directory_list_item, null);
cellHolder = new CellHolder();
cellHolder.textTitle = (TextView) view.findViewById(R.id.annuaire_titre_etablissement);
cellHolder.textCategory = (TextView) view.findViewById(R.id.annuaire_categorie_etablissement);
cellHolder.textDistance = (TextView) view.findViewById(R.id.annuaire_distance_etablissement);
cellHolder.imageIcon = (ImageView) view.findViewById(R.id.img_icon);
cellHolder.textPromo = (TextView) view.findViewById(R.id.promo);
cellHolder.textTarif = (TextView) view.findViewById(R.id.annuaire_tarif_etablissement);
view.setTag(cellHolder);
}
else {
cellHolder = (CellHolder) convertView.getTag();
}
//
// SET
cellHolder.textTitle.setText(_contact.getName().toUpperCase());
try {
//
EtablissementRepository etablissementRep = new EtablissementRepository(_activity);
etablissementRep.Open();
int idEta = etablissementRep.GetByIdContact(_contact.getIdentifiant());
etablissement = etablissementRep.GetById(idEta);
etablissementRep.Close();
// CATEGORIES
if (_section == 0) {
if (etablissement.getSection() != null && !etablissement.getSection().getLibelle().equals("")) {
cellHolder.textCategory.setText(etablissement.getSection().getLibelle());
}
else {
cellHolder.textCategory.setVisibility(View.GONE);
}
}
else {
String categories = "";
for (Categorie cat : etablissement.getCategories()) {
categories = categories + cat.getLibelle() + "|";
}
if (!categories.equals("")) {
cellHolder.textCategory.setText(categories);
}
else {
cellHolder.textCategory.setText(_activity.getString(R.string.txt_no_categories));
}
}
//
// TARIF
String trancheTarif = "";
if (etablissement.getTarif() != null) {
trancheTarif = etablissement.getTarif().getMinPrice() + "\u20ac à " + etablissement.getTarif().getMaxPrice() + "\u20ac";
}
if (!trancheTarif.equals("") && etablissement.getTarif().getMinPrice() > 0 && etablissement.getTarif().getMaxPrice() > 0) {
cellHolder.textTarif.setText(trancheTarif);
}
else {
cellHolder.textTarif.setText("- \u20ac à - \u20ac");
}
// PROMO
boolean etatPromotion = false;
for (Promotion promo : etablissement.getPromotions()) {
if (promo.isPromoOnGoing()) {
etatPromotion = true;
}
}
if (!etatPromotion) { // PROMO OFF
cellHolder.textPromo.setVisibility(View.VISIBLE);
}
else { // PROMO ON
cellHolder.textPromo.setVisibility(View.VISIBLE);
}
// LOGO
final ProgressBar spinner = (ProgressBar) convertView.findViewById(R.id.loading);
_imageLoader.displayImage(etablissement.getImgThumb(), cellHolder.imageIcon, _options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason.getType()) {
case IO_ERROR:
message = "Input/Output error";
break;
case DECODING_ERROR:
message = "Image can't be decoded";
break;
case NETWORK_DENIED:
message = "Downloads are denied";
break;
case OUT_OF_MEMORY:
message = "Out Of Memory error";
break;
case UNKNOWN:
message = "Unknown error";
break;
}
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
}
});
}
catch (Exception e) {
}
// DISTANCE
int distanceFormatee = 0;
if (_latitude == 0 || _longitude == 0) {
cellHolder.textDistance.setText("");
}
else {
int distance = (int) distanceBetween(_latitude, _longitude, _contact.getLatitude(), _contact.getLongitude());
distanceFormatee = distance / 1000;
if (distance < 1000) {
cellHolder.textDistance.setText("< 1 km");
}
else {
cellHolder.textDistance.setText(distanceFormatee + " km");
}
}
//
// SAVE DISTANCE
EtablissementApplication._dataManager.get_listOfContacts(_section, _activity).get(position).setDistance(distanceFormatee);
//
// DATA SAVE
List<Integer> _mapData = new ArrayList<Integer>();
_mapData.add(_contact.getIdentifiant());
_mapData.add(etablissement.getIdentifiant());
DataManager._contactForEtaHashMap.put(_contact.getName(), etablissement);
DataManager._mapContact.put(position, _mapData);
return view;
}
public class CellHolder {
public TextView textTitle;
public TextView textAdress;
public TextView textCategory;
public TextView textTarif;
public TextView textPromo;
public ImageView imageIcon;
public TextView textDistance;
}
public void clearData() {
_listContacts.clear();
_listFavoris.clear();
}
private double distanceBetween(float lat_a, float lng_a, float lat_b, float lng_b) {
float pk = (float) (180 / 3.14169);
float a1 = lat_a / pk;
float a2 = lng_a / pk;
float b1 = lat_b / pk;
float b2 = lng_b / pk;
float t1 = FloatMath.cos(a1) * FloatMath.cos(a2) * FloatMath.cos(b1) * FloatMath.cos(b2);
float t2 = FloatMath.cos(a1) * FloatMath.sin(a2) * FloatMath.cos(b1) * FloatMath.sin(b2);
float t3 = FloatMath.sin(a1) * FloatMath.sin(b1);
double tt = Math.acos(t1 + t2 + t3);
return 6366000 * tt;
}
}
You can achieve expected behaviour by this:
Your list item layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<ImageView
android:id="#+id/imgAlbum"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_gravity="center|left"
android:scaleType="centerCrop" />
</RelativeLayout
If you have ProgressBar and ImageView in this order, then ImageView will overlay the ProgressBar, when Image Loader set image into it so ProgressBar will not be visible anymore.
Then in your getView() method just simply load image with standard way. You dont have to bother with hiding/showing ProgressBar
You will have to put a function to refresh the 'source' that is providing the image resource to the spinner manually once the download is complete i.e i suppose when an onPost is complete in your async task if at all u are using one. This way the source providing the resource to the spinner will be updated all the time.
try this code and use Asynk task will help u:
http://thinkandroid.wordpress.com/2012/06/13/lazy-loading-images-from-urls-to-listviews/