Java tutorial
package cl.smartcities.isci.transportinspector.adapters.dialogAdapters; import android.app.AlertDialog; import android.content.Context; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatImageView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageButton; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import cl.smartcities.isci.transportinspector.R; import cl.smartcities.isci.transportinspector.TranSappApplication; import cl.smartcities.isci.transportinspector.backend.Bus; import cl.smartcities.isci.transportinspector.backend.Service; import cl.smartcities.isci.transportinspector.dialogs.BusListDialog; import cl.smartcities.isci.transportinspector.drawables.BusListReportsDrawable; import cl.smartcities.isci.transportinspector.serviceVisibility.ServiceVisibilityController; import cl.smartcities.isci.transportinspector.utils.DebouncedOnClickListener; /** * Created by Ivana on 28-10-15. * Refactored by aantoine on 14-06-16 * <p/> * Adapter that shows a list with the buses coming to a certain bus stop and information related * to every bus on some ListView. */ public class IncomingBusesAdapter extends MultiStateArrayAdapter<Service, IncomingBusesAdapter.RowState> { private final float scale; private final int onIconColor; private final int onOffIconColor; private final int offIconColor; AlertDialog alertDialog; Typeface typeface; ArrayList<Service> services; final ArrayList<Service> originalServices; LayoutInflater mInflater; Context context; Drawable prev; Drawable next; Drawable onIcon; Drawable onOffIcon; Drawable offIcon; private String busStop; private List<String> viewStateMap; private AppCompatImageView visibilityIcon; public BusListDialog.OnDestroyListener getOnDestroyListener() { return new BusListDialog.OnDestroyListener() { @Override public void onDestroy() { ServiceVisibilityController.notifyNewState(viewStateMap); } }; } public void setVisibilityIcon(AppCompatImageView visibilityIcon) { this.visibilityIcon = visibilityIcon; } public enum RowState { FIRST_BUS, SECOND_BUS } public IncomingBusesAdapter(Context pContext, ArrayList<Service> pServices, String busStop) { super(pContext, R.layout.bus_list_row); this.busStop = busStop; originalServices = pServices; loadViewState(); this.typeface = Typeface.createFromAsset(pContext.getAssets(), pContext.getString(R.string.icon_font)); this.mInflater = (LayoutInflater) pContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.context = pContext; this.next = ContextCompat.getDrawable(this.context, R.drawable.ic_navigate_next_black_36dp); this.prev = ContextCompat.getDrawable(this.context, R.drawable.ic_navigate_before_black_36dp); this.scale = getContext().getResources().getDisplayMetrics().density; this.onIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_on_28dp); this.onOffIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_on_28dp); this.offIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_off_28dp); this.onIconColor = ContextCompat.getColor(getContext(), R.color.green_button); this.offIconColor = ContextCompat.getColor(getContext(), R.color.color_grey_off); this.onOffIconColor = ContextCompat.getColor(getContext(), R.color.background_white); } private void loadViewState() { this.viewStateMap = ServiceVisibilityController.getStateForServices(getContext(), busStop); this.services = reorderServices(); } @Override protected RowState getDefaultState() { return RowState.FIRST_BUS; } /* amount of rows that will be drawn on the list */ @Override public int getCount() { if (this.services != null) return this.services.size(); else return 1; } private void setCorrectView(final ViewHolder holder, final int position, Service service) { final String serviceName = service.getServiceName(); ArrayList<Bus> buses = service.getBuses(); holder.bus.setText(serviceName); Bus selectedBus; final ArrayList<Bus> finalBuses = service.getBuses(); holder.moreButton.setVisibility(View.VISIBLE); if (getLastStateAccordingToPosition(position) == RowState.FIRST_BUS) { selectedBus = buses.get(0); ((ViewGroup.MarginLayoutParams) holder.amountOfReports.getLayoutParams()).leftMargin = (int) (0 * scale + 0.5f); holder.moreButton.setImageDrawable(next); holder.moreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setCurrentState(position, RowState.SECOND_BUS); setCorrectView(holder, position, services.get(position)); Map<String, String> attributes = new HashMap<>(); attributes.put("Service code", serviceName); TranSappApplication.addFabricLog("Next Bus Icon Clicked", attributes); } }); holder.amountOfReports.setOnClickListener(new DebouncedOnClickListener(1000) { @Override public void onDeBouncedClick(View v) { setEventsList(position, finalBuses, 1); } }); } else { selectedBus = buses.get(1); holder.moreButton.setImageDrawable(prev); holder.moreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setCurrentState(position, RowState.FIRST_BUS); setCorrectView(holder, position, services.get(position)); } }); holder.amountOfReports.setOnClickListener(new DebouncedOnClickListener(1000) { @Override public void onDeBouncedClick(View v) { setEventsList(position, finalBuses, 2); } }); } int reports = selectedBus.getAmountOfReports(); holder.amountOfReports .setImageDrawable(new BusListReportsDrawable(this.context, reports, selectedBus.getBusIcon())); holder.busTime.setText(selectedBus.getTime()); holder.busDistance.setText(selectedBus.getFormattedDistance()); holder.busPlate.setText(selectedBus.getFormattedPlate()); } private void addToCurrentState(String serviceName) { if (!viewStateMap.contains(serviceName)) { viewStateMap.add(serviceName); } } private void deleteFromCurrentState(String serviceName) { viewStateMap.remove(serviceName); } private boolean isVisible(String serviceName) { return !viewStateMap.contains(serviceName); } private void setViewIconOn(final AppCompatImageView viewIcon, final Service service) { viewIcon.setImageDrawable(onIcon); viewIcon.setColorFilter(onIconColor); viewIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addToCurrentState(service.getServiceName()); ServiceVisibilityController.changeServiceState(getContext(), busStop, service, false); setViewIcon(visibilityIcon); reorderAndInvalidate(); } }); } private void reorderAndInvalidate() { this.services = reorderServices(); this.notifyDataSetChanged(); } private ArrayList<Service> reorderServices() { ArrayList<Service> onServices = new ArrayList<>(); ArrayList<Service> offServices = new ArrayList<>(); for (Service service : originalServices) { if (isVisible(service.getServiceName())) { onServices.add(service); } else { offServices.add(service); } } onServices.addAll(offServices); return onServices; } private void setViewIconOff(final AppCompatImageView viewIcon, final Service service) { viewIcon.setImageDrawable(offIcon); viewIcon.setColorFilter(offIconColor); viewIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { deleteFromCurrentState(service.getServiceName()); ServiceVisibilityController.changeServiceState(getContext(), busStop, service, true); setViewIcon(visibilityIcon); reorderAndInvalidate(); } }); } /* set the view for the adapter */ public View getView(final int position, View convertView, ViewGroup parent) { /* here for every row a view is set. Each row can show 2 buses. Every pair of buses belongs to one service. */ ViewHolder holder; /* set view if this is the first time using it */ if (convertView == null) { convertView = mInflater.inflate(R.layout.bus_list_row, parent, false); holder = new ViewHolder(); /* First bus (the one that is nearer to the bus stop)*/ holder.bus = (TextView) convertView.findViewById(R.id.bus_route); holder.amountOfReports = (ImageButton) convertView.findViewById(R.id.amount_of_bus_reports); holder.busTime = (TextView) convertView.findViewById(R.id.bus_time_to_bus_stop); holder.busDistance = (TextView) convertView.findViewById(R.id.bus_distance_to_bus_stop); holder.busPlate = (TextView) convertView.findViewById(R.id.bus_plate); holder.moreButton = (AppCompatImageView) convertView.findViewById(R.id.next_bus); holder.moreButton.setImageDrawable(this.next); holder.viewIcon = (AppCompatImageView) convertView.findViewById(R.id.show_on_off_icon); /* get necessary Typefaces */ Typeface robotoRegular = Typeface.createFromAsset(this.getContext().getAssets(), this.context.getString(R.string.roboto_regular_font)); Typeface robotoBold = Typeface.createFromAsset(this.getContext().getAssets(), this.context.getString(R.string.roboto_bold_font)); holder.setHolderTypefaceRegular(robotoRegular); holder.setHolderTypefaceBold(robotoBold); /* save holder */ convertView.setTag(holder); } /* If is not the first time we can recharge it */ else { holder = (ViewHolder) convertView.getTag(); } final Service service = services.get(position); if (!service.isEmptyService()) { setCorrectView(holder, position, service); if (service.getBuses().size() == 1) { holder.moreButton.setClickable(false); holder.moreButton.setVisibility(View.INVISIBLE); } } /* if there are no buses coming we show the service anyway */ else { String serviceName = service.getServiceName(); holder.bus.setText(serviceName); holder.busTime.setText(context.getString(R.string.not_license_plate)); holder.busDistance.setText(context.getString(R.string.not_info_for_any_bus)); holder.busPlate.setText(context.getString(R.string.not_license_plate)); holder.moreButton.setVisibility(View.GONE); holder.amountOfReports.setImageDrawable(new BusListReportsDrawable(this.context, 0, R.drawable.bus01)); } if (isVisible(service.getServiceName())) { setViewIconOn(holder.viewIcon, service); } else { setViewIconOff(holder.viewIcon, service); } /* background is set with slightly different colors depending if the row is odd or not */ if (position % 2 == 1) { int backGroundColor = ContextCompat.getColor(context, R.color.odd_row); convertView.setBackgroundColor(backGroundColor); } else { int backGroundColor = ContextCompat.getColor(context, R.color.even_row); convertView.setBackgroundColor(backGroundColor); } return convertView; } @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); } public void setDialog(AlertDialog dialog) { this.alertDialog = dialog; } /* this sets the view of the current ListView to the bus list */ private void setBusesList(String pBusStopCode, String pBusStopTitle) { Button backButton = (Button) this.alertDialog.findViewById(R.id.back_button); TextView titleCode = (TextView) this.alertDialog.findViewById(R.id.bus_stop_code); TextView titleName = (TextView) this.alertDialog.findViewById(R.id.bus_stop_title); AppCompatImageView visibilityIcon = (AppCompatImageView) this.alertDialog .findViewById(R.id.visibility_icon); setViewIcon(visibilityIcon); /* set title elements */ backButton.setVisibility(View.INVISIBLE); backButton.setClickable(false); titleCode.setText(pBusStopCode); titleName.setText(pBusStopTitle); /* set AlertDialog content view*/ ListView listView = this.alertDialog.getListView(); IncomingBusesAdapter adapter = new IncomingBusesAdapter(this.context, this.services, busStop); adapter.setDialog(this.alertDialog); adapter.setVisibilityIcon(visibilityIcon); listView.setAdapter(adapter); } private int hashMapState() { boolean someActive = false; boolean someInactive = false; for (Service service : originalServices) { if (isVisible(service.getServiceName())) { someActive = true; } else { someInactive = true; } } if (someActive && someInactive) { return 3; } else if (someActive) { return 2; } return 1; } public void setViewIcon(final AppCompatImageView visibilityIcon) { visibilityIcon.setVisibility(View.VISIBLE); int state = hashMapState(); if (state == 1) { visibilityIcon.setColorFilter(offIconColor); visibilityIcon.setImageDrawable(offIcon); visibilityIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectAllOn(); setViewIcon(visibilityIcon); } }); } else if (state == 2) { visibilityIcon.setColorFilter(onIconColor); visibilityIcon.setImageDrawable(onIcon); visibilityIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectAllOff(); setViewIcon(visibilityIcon); } }); } else { visibilityIcon.setImageDrawable(onOffIcon); visibilityIcon.setColorFilter(onOffIconColor); visibilityIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectAllOn(); setViewIcon(visibilityIcon); } }); } } /* this sets the view of the current ListView to the event list of a bus */ private void setEventsList(int pRow, ArrayList<Bus> pBus, int pShowing) { /* get row view */ ListView listView = this.alertDialog.getListView(); View v = listView.getChildAt(pRow - listView.getFirstVisiblePosition()); if (v == null) return; /* get title elements */ Button backButton = (Button) this.alertDialog.findViewById(R.id.back_button); TextView titleCode = (TextView) this.alertDialog.findViewById(R.id.bus_stop_code); TextView titleName = (TextView) this.alertDialog.findViewById(R.id.bus_stop_title); AppCompatImageView visibilityIcon = (AppCompatImageView) this.alertDialog .findViewById(R.id.visibility_icon); final String busStopCode = ((TextView) this.alertDialog.findViewById(R.id.bus_stop_code)).getText() .toString(); final String busStopTitle = ((TextView) this.alertDialog.findViewById(R.id.bus_stop_title)).getText() .toString(); /* decides which bus was being shown */ int busIndex = pShowing - 1; /* shows the event list of the corresponding bus if there's at least one */ if (pBus.get(busIndex).getAmountOfReports() > 0) { String code = pBus.get(busIndex).getService(); String title = pBus.get(busIndex).getLicensePlate(); titleCode.setText(code); titleName.setText(title); /* set back button to the list bus view */ backButton.setVisibility(View.VISIBLE); visibilityIcon.setVisibility(View.GONE); backButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setBusesList(busStopCode, busStopTitle); } }); EventAdapter adapter = new EventAdapter(this.context, code, title, "Bus", pBus.get(busIndex).getEvents()); adapter.setDialog(this.alertDialog); listView.setAdapter(adapter); } } public void selectAllOn() { for (Service service : originalServices) { deleteFromCurrentState(service.getServiceName()); ServiceVisibilityController.changeServiceState(getContext(), busStop, service, true); } reorderAndInvalidate(); } public void selectAllOff() { for (Service service : originalServices) { addToCurrentState(service.getServiceName()); ServiceVisibilityController.changeServiceState(getContext(), busStop, service, false); } reorderAndInvalidate(); } /* ViewHolder to hold parameters */ private static class ViewHolder extends EditableViewHolder { ImageButton amountOfReports; TextView bus; TextView busTime; TextView busDistance; TextView busPlate; AppCompatImageView moreButton; AppCompatImageView viewIcon; @Override public void setHolderTypefaceRegular(Typeface font) { setFont(font, busTime); } @Override public void setHolderTypefaceBold(Typeface font) { setFont(font, bus, busDistance, busPlate); } @Override public void setHolderIconFont(Typeface font) { } } }