Search code examples
androidandroid-asynctaskcustomdialogdialogfragment

Custom progressbar dialog with dialogFragment


I'm new to android programming. I want to create a custom progress dialog with some textview and button and showing the progress with two progressBar and updating them while sending the files from Asynctask, Also I want it works with minimum API 10. google doc recommend me to use DialogFragment and i do not have any idea how to update the progress bars and textviews that are in that custom layout of my fragmentDialog, when I try to reference a textview or progress bar it throw null exeption

Here is my code

public static class FireMissilesDialogFragment extends DialogFragment {
    public FireMissilesDialogFragment(){
    }
    public static FireMissilesDialogFragment newInstance(String title) {
        FireMissilesDialogFragment frag = new FireMissilesDialogFragment();
        Bundle args = new Bundle();
        args.putString("title", title);
        frag.setArguments(args);
        return frag;
    }
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Get the layout inflater
        LayoutInflater inflater = this.getActivity().getLayoutInflater();
        // Inflate and set the layout for the dialog
        // Pass null as the parent view because its going in the dialog layout

        View view = inflater.inflate(R.layout.custom_progress, null);
        ProgressBar pbCurrent = (ProgressBar) view.findViewById(R.id.current);

        builder.setView(view);

        builder.setMessage("Fire Missiles")
        .setPositiveButton("Fire", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // FIRE ZE MISSILES!
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // User cancelled the dialog
            }
        });
        // Create the AlertDialog object and return it
        return builder.create();
    }
}

I got a nullExeption here in my main activity when try to reference a view

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button frag = (Button) findViewById(R.id.frag);
    frag.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FireMissilesDialogFragment fragment = FireMissilesDialogFragment.newInstance("hi") ;
            fragment.getActivity().findViewById(R.id.current);// nullExeption here
            //              downloadAsync as = new downloadAsync();
            //              as.execute();

        }
    });

I didn't see much question and example about that, did I go all the way wrong and should pick another way to achieve my point??!!

Edit : I'm trying to create something like this

thanks in advance


Solution

  • I can not do a full explanation but I can leave an example and then hopefully you can figure out a way to incorporate the things you need.

    The DialogFragment with an AsyncTask and a Progress bar:

    public class LoadHydrantsToMapTaskFragment extends DialogFragment {
    
        public static final String TAG = LoadHydrantsToMapTaskFragment.class
                .getSimpleName();
    
        public interface LoadHydrantsToMapTaskCallback {
            void onPreExecute(int maxProgress);
    
            void onProgressUpdate(int progress);
    
            void onCancelled();
    
            void onPostExecute();
        }
    
        private LoadHydrantsToMapTask mTask;
        // private ProgressBar mProgressBar;
    
        private List<HydrantHolder> mHydrants;
    
        private GoogleMap map;
    
        public static LoadHydrantsToMapTaskFragment newInstance(
                List<HydrantHolder> hydrants, GoogleMap map) {
            LoadHydrantsToMapTaskFragment taskFragment = new LoadHydrantsToMapTaskFragment();
            taskFragment.mHydrants = hydrants;
            taskFragment.map = map;
    
            return taskFragment;
        }
    
        @Override public void onAttach(Activity activity) {
            super.onAttach(activity);
    
        }
    
        @Override public View onCreateView(LayoutInflater inflater,
                ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.dialog_progress_task, container);
            mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
            mProgressBar.setProgress(0);
            mProgressBar.setMax(mHydrants.size());
    
            getDialog().setTitle(getActivity().getString(R.string.adding_hydrants));
            // This dialog can't be canceled by pressing the back key.
            getDialog().setCancelable(false);
            getDialog().setCanceledOnTouchOutside(false);
    
            return view;
        }
    
        /**
         * This method will only be called once when the retained Fragment is first
         * created.
         */
        @Override public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setStyle(SherlockDialogFragment.STYLE_NORMAL, R.style.TuriosDialog);
    
            // Retain this fragment across configuration changes.
            setRetainInstance(true);
    
            mTask = new LoadHydrantsToMapTask(mHydrants);
            mTask.setCallback(new LoadHydrantsToMapTaskCallback() {
    
                @Override public void onPreExecute(int maxProgress) {
                }
    
                @Override public void onProgressUpdate(int progress) {
                    mProgressBar.setProgress(progress);
                }
    
                @Override public void onPostExecute() {
                    if (isResumed())
                        dismiss();
    
                    mTask = null;
    
                }
    
                @Override public void onCancelled() {
                    if (isResumed())
                        dismiss();
    
                    mTask = null;
                }
            });
    
            mTask.execute();
        }
    
        @Override public void onResume() {
            super.onResume();
    
            // This is a little hacky, but we will see if the task has finished
            // while we weren't
            // in this activity, and then we can dismiss ourselves.
            if (mTask == null)
                dismiss();
        }
    
        @Override public void onDetach() {
            super.onDetach();
        }
    
        // This is to work around what is apparently a bug. If you don't have it
        // here the dialog will be dismissed on rotation, so tell it not to dismiss.
        @Override public void onDestroyView() {
            if (getDialog() != null && getRetainInstance())
                getDialog().setDismissMessage(null);
            super.onDestroyView();
        }
    
        // Also when we are dismissed we need to cancel the task.
        @Override public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);
            // If true, the thread is interrupted immediately, which may do bad
            // things.
            // If false, it guarantees a result is never returned (onPostExecute()
            // isn't called)
            // but you have to repeatedly call isCancelled() in your
            // doInBackground()
            // function to check if it should exit. For some tasks that might not be
            // feasible.
            if (mTask != null)
                mTask.cancel(false);
    
        }
    
        private class LoadHydrantsToMapTask extends
                AsyncTask<Void, Integer, List<MarkerOptions>> {
            // Before running code in separate thread
            List<HydrantHolder> mHydrants;
            LoadHydrantsToMapTaskCallback mLoadHydrantsToMapTaskCallback;
    
            public LoadHydrantsToMapTask(List<HydrantHolder> hydrants) {
                this.mHydrants = hydrants;
            }
    
            public void setCallback(
                    LoadHydrantsToMapTaskCallback loadHydrantsToMapTaskCallback) {
                this.mLoadHydrantsToMapTaskCallback = loadHydrantsToMapTaskCallback;
            }
    
            @Override protected void onPreExecute() {
    
                if (mLoadHydrantsToMapTaskCallback != null) {
                    mLoadHydrantsToMapTaskCallback.onPreExecute(mHydrants.size());
                }
    
            }
    
            // The code to be executed in a background thread.
            @Override protected List<MarkerOptions> doInBackground(Void... arg) {
                List<MarkerOptions> markers = new ArrayList<MarkerOptions>();
    
                for (HydrantHolder hydrant : mHydrants) {
    
                    final String hydrant_type = hydrant.getHydrantType();
                    final String hydrant_icon_path = hydrant.getIconPath();
                    double latitude = hydrant.getLatitude();
                    double longitude = hydrant.getLongitude();
    
                    final LatLng position = new LatLng(latitude, longitude);
    
                    final String address = hydrant.getAddress();
                    final String addressNumber = hydrant.getAddressNumber();
                    final String addressremark = hydrant.getAddressRemark();
                    final String remark = hydrant.getRemark();
    
                    // Log.d(TAG, hydrant.toString());
    
                    BitmapDescriptor icon = BitmapDescriptorFactory
                            .defaultMarker(BitmapDescriptorFactory.HUE_RED);
    
                    if (!hydrant_icon_path.isEmpty()) {
                        File iconfile = new File(hydrant_icon_path);
                        if (iconfile.exists()) {
                            BitmapDescriptor loaded_icon = BitmapDescriptorFactory
                                    .fromPath(hydrant_icon_path);
                            if (loaded_icon != null) {
                                icon = loaded_icon;
                            } else {
                                Log.e(TAG, "loaded_icon was null");
                            }
                        } else {
                            Log.e(TAG, "iconfile did not exist: "
                                    + hydrant_icon_path);
                        }
                    } else {
                        Log.e(TAG, "iconpath was empty on hydrant type: "
                                + hydrant_type);
                    }
    
                    StringBuffer snippet = new StringBuffer();
                    if (!address.isEmpty())
                        snippet.append("\n" + address + " " + addressNumber);
                    if (addressremark.isEmpty())
                        snippet.append("\n" + addressremark);
                    if (!remark.isEmpty())
                        snippet.append("\n" + remark);
    
                    markers.add(new MarkerOptions().position(position)
                            .title(hydrant_type).snippet(snippet.toString())
                            .icon(icon));
    
                    publishProgress(markers.size());
                }
                return markers;
            }
    
            // Update the progress
            @Override protected void onProgressUpdate(Integer... values) {
                if (mLoadHydrantsToMapTaskCallback != null) {
                    mLoadHydrantsToMapTaskCallback.onProgressUpdate(values[0]);
                }
            }
    
            @Override protected void onCancelled() {
                if (mLoadHydrantsToMapTaskCallback != null) {
                    mLoadHydrantsToMapTaskCallback.onCancelled();
                }
            }
    
            // after executing the code in the thread
            @Override protected void onPostExecute(List<MarkerOptions> markers) {
    
                for (MarkerOptions marker : markers) {
                    if (marker != null && map != null)
                        map.addMarker(marker);
                }
    
                if (mLoadHydrantsToMapTaskCallback != null) {
                    mLoadHydrantsToMapTaskCallback.onPostExecute();
                }
    
            }
    
        }
    
    }
    

    My dialog_progress_task layout:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
    
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:maxHeight="10dip"
            android:minHeight="10dip"
            android:progress="0"
            android:progressDrawable="@drawable/progress_orange" />
    
    </LinearLayout>
    

    And finally the code I use to add it:

    @Override public void loadHydrantsToMap(List<HydrantHolder> hydrants,
            GoogleMap map) {
    
        LoadHydrantsToMapTaskFragment loadHydrantsFragment;
    
        if (fm != null) {
            FragmentTransaction ft = fm.beginTransaction();
            loadHydrantsFragment = (LoadHydrantsToMapTaskFragment) fm
                    .findFragmentByTag(LoadHydrantsToMapTaskFragment.TAG);
            if (loadHydrantsFragment != null) {
                Log.i("Attatching LoadHydrantsToMapTaskFragment");
                ft.attach(loadHydrantsFragment);
            } else {
                loadHydrantsFragment = LoadHydrantsToMapTaskFragment
                        .newInstance(hydrants, map);
                Log.i("Adding new LoadHydrantsToMapTaskFragment");
                ft.add(loadHydrantsFragment, LoadHydrantsToMapTaskFragment.TAG);
            }
            ft.commit();
        }
    }