Android Music Player inside a fragment - java

I am implementing a music player app. I am able to fetch the songs from the sd card. But stuck in something from hours i.e. I am unable to make the songs play inside the fragment.
Here is the MainActivity class which is having 3 tab fragments.
public class MainActivity extends AppCompatActivity {
private final String[] TITLES = {"Now playing", "Library", "Groups"};
private static boolean isInForeground = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//if (savedInstanceState == null) {}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Initialize the ViewPager and set an adapter
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new PagerAdapter(getSupportFragmentManager(), getBaseContext()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setShouldExpand(true);
tabs.setViewPager(pager);
//Whenever the user changes tab, we want the title to change too
tabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void onPageSelected(int position) {
setTitle(TITLES[position]);
}
});
//We want to have the library as default view
pager.setCurrentItem(1);
setTitle(TITLES[1]);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
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);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class MainFragment extends Fragment {
public MainFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_song_library, container, false);
return view;
}
}
public class PagerAdapter extends FragmentPagerAdapter
implements PagerSlidingTabStrip.CustomTabProvider {
private ArrayList<Integer> tab_icon = new ArrayList<Integer>();
Context myContext;
public PagerAdapter(FragmentManager fm, Context context) {
super(fm);
myContext = context;
tab_icon.add(context.getResources().getIdentifier("ic_play_arrow_white_36dp", "drawable", context.getPackageName()));
tab_icon.add(context.getResources().getIdentifier("ic_list_white_36dp", "drawable", context.getPackageName()));
tab_icon.add(context.getResources().getIdentifier("ic_group_white_36dp", "drawable", context.getPackageName()));
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
if(position == 0){
return SongNowPlayingFragment.newInstance();
} else if (position == 1){
return SongLibraryFragment.newInstance();
} else if(position == 2){
return GroupFragment.newInstance();
}
System.err.println("Invalid tab fragment!");
return new Fragment();
}
#Override
public View getCustomTabView(ViewGroup viewGroup, int position) {
LinearLayout imageView = (LinearLayout) LayoutInflater.from(myContext)
.inflate(R.layout.tab_layout, null, false);
ImageView tabImage = (ImageView) imageView.findViewById(R.id.tabImage);
tabImage.setImageResource(tab_icon.get(position));
return imageView;
}
}
#Override
protected void onResume()
{
super.onResume();
isInForeground = true;
}
#Override
protected void onPause()
{
super.onPause();
isInForeground = false;
}
static boolean isInForeground(){
return isInForeground;
}
}
This is the SongLibraryFragment in which I have added the songs from the user device. Now I want to play those songs.
public class SongLibraryFragment extends Fragment implements MediaPlayerControl {
private ArrayList<SongItem> songList;
private ListView songView;
private MusicService musicSrv;
private Intent playIntent;
private boolean musicBound=false;
private MusicController controller;
private boolean paused=false, playbackPaused=false;
private MainActivity mainActivity = null;
public static SongLibraryFragment newInstance() {
SongLibraryFragment f = new SongLibraryFragment();
Bundle b = new Bundle();
f.setArguments(b);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_song_library, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mainActivity = (MainActivity) SongLibraryFragment.this.getActivity();
songView = (ListView) getView().findViewById(R.id.library_song_list);
songList = new ArrayList<SongItem>();
getSongList();
SongAdapter songAdt = new SongAdapter(getActivity(), songList);
songView.setAdapter(songAdt);
Collections.sort(songList, new Comparator<SongItem>() {
public int compare(SongItem a, SongItem b) {
return a.getTitle().compareTo(b.getTitle());
}
});
setController();
}
//connect to the service
private ServiceConnection musicConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicBinder binder = (MusicBinder)service;
//get service
musicSrv = binder.getService();
//pass list
musicSrv.setList(songList);
musicBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
#Override
public void onStart() {
super.onStart();
if(playIntent==null){
playIntent = new Intent(getActivity(), MusicService.class);
this.getActivity().bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
this.getActivity().startService(playIntent);
}
}
public void songPicked(View view){
musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
musicSrv.playSong();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
public void getSongList() {
//retrieve song info
ContentResolver musicResolver = getActivity().getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
if(musicCursor!=null && musicCursor.moveToFirst()){
//get columns
int titleColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.ARTIST);
//add songs to list
do {
long thisId = musicCursor.getLong(idColumn);
String thisTitle = musicCursor.getString(titleColumn);
String thisArtist = musicCursor.getString(artistColumn);
songList.add(new SongItem(thisId, thisTitle, thisArtist));
}
while (musicCursor.moveToNext());
}
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public int getCurrentPosition() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getPosn();
else return 0;
}
#Override
public int getDuration() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getDur();
else return 0;
}
#Override
public boolean isPlaying() {
if(musicSrv!=null && musicBound)
return musicSrv.isPng();
return false;
}
#Override
public void pause() {
playbackPaused=true;
musicSrv.pausePlayer();
}
#Override
public void seekTo(int pos) {
musicSrv.seek(pos);
}
#Override
public void start() {
musicSrv.go();
}
private void setController(){
//set the controller up
controller = new MusicController(getActivity());
controller.setPrevNextListeners(new View.OnClickListener() {
#Override
public void onClick(View v) {
playNext();
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
playPrev();
}
});
controller.setMediaPlayer(this);
controller.setAnchorView(getActivity().findViewById(R.id.library_song_list));
controller.setEnabled(true);
}
//play next
private void playNext(){
musicSrv.playNext();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
//play previous
private void playPrev(){
musicSrv.playPrev();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
#Override
public void onPause(){
super.onPause();
paused=true;
}
#Override
public void onResume(){
super.onResume();
if(paused){
setController();
paused=false;
}
}
#Override
public void onStop() {
controller.hide();
super.onStop();
}
#Override
public void onDestroy() {
this.getActivity().stopService(playIntent);
musicSrv=null;
super.onDestroy();
}
SongAdapter class
public class SongAdapter extends BaseAdapter {
private ArrayList<SongItem> songs;
private LayoutInflater songInf;
public SongAdapter(Context c, ArrayList<SongItem> theSongs){
songs=theSongs;
songInf=LayoutInflater.from(c);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return songs.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//map to song layout
LinearLayout songLay = (LinearLayout)songInf.inflate
(R.layout.song, parent, false);
//get title and artist views
TextView songView = (TextView)songLay.findViewById(R.id.song_title);
TextView artistView = (TextView)songLay.findViewById(R.id.song_artist);
//ImageView imageView = (ImageView)songLay.findViewById(R.id.song_image);
//get song using position
SongItem currSong = songs.get(position);
//get title and artist strings
songView.setText(currSong.getTitle());
artistView.setText(currSong.getArtist());
//imageView.setImage(currSong.getImage());
//set position as tag
songLay.setTag(position);
return songLay;
}
Song.xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp"
android:onClick="songPicked">
<TextView
android:id="#+id/song_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
style="#style/Base.TextAppearance.AppCompat.Title"
android:textColor="#color/primary_text_default_material_light"/>
<TextView
android:id="#+id/song_artist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
style="#style/Base.TextAppearance.AppCompat.Subhead"
android:textColor="#color/secondary_text_default_material_light"/>
</LinearLayout>
Error
java.lang.IllegalStateException: Could not find a method
songPicked(View) in the activity class
co.adrianblan.noraoke.MainActivity for onClick handler on view class
android.widget.LinearLayout
So the main problem is with the songPicked method inside SongFragmentLibrary. I have added the onClick: songPicked in the song.xml file but it is searching for the songPicked method inside the MainActivity. I am not getting what is the problem.
Please can anyone help me with this?

You are trying to set onclick listener from your fragment xml android:onClick="songPicked", you can't set onclick listener for a view which is part of fragment, in your getView() setOnClickListener:
LinearLayout songLay = (LinearLayout)songInf.inflate
(R.layout.song, parent, false);
songLay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Handle click event
}
})
OR
You can simply set OnItemClickListener on your listview
list.setOnItemClickListener(this);// implement OnItemClickListener in your fragment class

Related

get context after returning from adapter to fragment

I am using contextual action bar in my fragment("UnitsFragment.java") to delete and edit items of recyclerview. But when I come back from recyclerview adapter class("UnitsRv.java"). The context seems to be null. I tried returning context from adapter and it worked for function "prepareSelection". However for "onActionItemClicked" under ActionMode.callback, I need to get context so that I can use alertdialog for editing the items.
The "requireContext()" throws this error: Fragment UnitsFragment{e3a36c8 (b4957397-055a-4b1c-8af2-fee89a3e9b35)} not attached to a context.
Here are my codes.
UnitsFragment.java
public class UnitsFragment extends Fragment {
private static final String TAG = "UnitsFragment";
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<UnitsList> unitsLists = new ArrayList<>();
Activity mcontext = getActivity();
Context dcontext;
ActionMode actionMode;
public static ArrayList<UnitsList> selectionList = new ArrayList<>();
public static boolean isInActionMode = false;
List<String> list = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao().findUnitNameList();
public UnitsFragment() {
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_item_action, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_edit:
if (selectionList.size() == 1) {
final EditText editText = new EditText(requireContext());
new AlertDialog.Builder(requireContext())
.setTitle("Rename unit name").setView(editText)
.setPositiveButton("Rename", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
UnitsList unitsList = selectionList.get(0);
unitsList.setUnit_name(editText.getText().toString().trim());
isInActionMode = false;
((UnitsRv) mAdapter).changeDataItem(getCheckedLastPosition(), unitsList);
actionMode.finish();
selectionList.clear();
}
})
.create()
.show();
Toast.makeText(getContext(), "Edit", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
case R.id.menu_item_delete:
isInActionMode = false;
((UnitsRv) mAdapter).removeData(selectionList);
Toast.makeText(getContext(), "Delete", Toast.LENGTH_SHORT).show();
actionMode.finish();
selectionList.clear();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
}
};
private int getCheckedLastPosition() {
ArrayList<UnitsList> dataSet = UnitsRv.getDataSet();
for (int i = 0; i < dataSet.size(); i++) {
if (dataSet.get(i).equals(selectionList.get(0))) {
return i;
}
}
return 0;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
dcontext = rootView.getContext();
Log.d(TAG, "onCreateView1: " + dcontext);
recyclerView = rootView.findViewById(R.id.rv_units);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.HORIZONTAL));
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL));
layoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(layoutManager);
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
Log.d(TAG, "onCreateView: " + getContext());
mAdapter = new UnitsRv(mcontext,unitsLists);
recyclerView.setAdapter(mAdapter);
return rootView;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.add, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new:
final View customLayout = getLayoutInflater().inflate(R.layout.add_unit_dialog, null);
final EditText edt_unit_name = customLayout.findViewById(R.id.edt_new_unit_name);
final AlertDialog dialog = new AlertDialog.Builder(getContext())
.setView(customLayout)
.setTitle("Unit name")
.setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
Button ok_btn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button cancel_btn = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
ok_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String unit_name = edt_unit_name.getText().toString().trim();
if (!TextUtils.isEmpty(unit_name)) {
String old_unit_name = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.findByUnitName(unit_name);
if (old_unit_name == null) {
DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.insertUnits(new UnitsList(unit_name));
unitsLists.add(new UnitsList(unit_name));
dialog.dismiss();
} else {
edt_unit_name.setError("Unit already exists");
}
} else {
edt_unit_name.setError("Can't be empty");
}
}
});
cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
}
});
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists);
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
private void updateViewCounter() {
int counter = selectionList.size();
if (counter == 1) {
actionMode.setTitle(counter + "item selected");
} else {
actionMode.setTitle(counter + "items selected");
}
}
}
This is my Adapter class.
UnitsRv.java
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment();
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists) {
mcontext = context;
munitsLists = unitsLists;
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
unitsFragment.prepareSelection(mcontext,getAdapterPosition());
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
unitsFragment.prepareSelection(view.getContext(),getAdapterPosition());
return true;
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.units_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.unit_name.setText(munitsLists.get(position).getUnit_name());
if (UnitsFragment.isInActionMode){
if (UnitsFragment.selectionList.contains(munitsLists.get(position))){
holder.itemView.setBackgroundResource(R.color.colorSelected);
}
}
}
#Override
public int getItemCount() {
return munitsLists.size();
}
public static ArrayList<UnitsList> getDataSet() {
return munitsLists;
}
public void changeDataItem(int position, UnitsList unitsList) {
munitsLists.set(position, unitsList);
notifyDataSetChanged();
}
public void removeData(ArrayList<UnitsList> list) {
for (UnitsList unitsList : list) {
munitsLists.remove(unitsList);
}
notifyDataSetChanged();
}
}
First, you should not create instance of your UnitsFragment inside your adapter.
You can use EventBus to communicate between Activities, Fragments, Adapters, etc.
Or You can do your task using interface. like below.
Create an interface like this
public interface AdapterCallback {
void prepareSelection(Context context,int position);
}
In your UnitsFragment implement the above interface. like the following
public class UnitsFragment extends Fragment implements AdapterCallback{
// your other codes
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
// .... your other codes
Log.d(TAG, "onCreateView: " + getContext());
// modify below line like this
mAdapter = new UnitsRv(mcontext, unitsLists, this); // here you have to pass an extra parameter that will implement your callback method from adapter.
recyclerView.setAdapter(mAdapter);
return rootView;
}
// ... you other codes
#Override
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists,this); // add this as parameter.
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
// other codes
}
Now, inside your Adapter you need to add an extra argument in constructor of UnitsRv and call your interface method from adapter ussing mAdapterCallback.
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment(); // remove this line
private AdapterCallback mAdapterCallback; // add this line
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists, AdapterCallback callback) {
mcontext = context;
munitsLists = unitsLists;
this.mAdapterCallback = callback; // add this line
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
mAdapterCallback.prepareSelection(mcontext,getAdapterPosition()); // modify this line
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
mAdapterCallback.prepareSelection(view.getContext(),getAdapterPosition()); // modify this line
return true;
}
}
// your other codes....
}
You should check for your fragment is attached or not with isAdded()
place if(!isAdded()) return in your onActionItemClicked. and replace requireContext() with getContext() because requireContext() always throws IllegalStateException if fragment is not attached.
override onAttach method to save context in your fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context= context;
}
Hope this helps.

Is RecyclerView refreshed when AlertDialog's positive button gets pressed

My MainActivity has a RecyclerView adapter, and data to this RecyclerView is added through a AlertDialog which passes the entered text to the MainActivity. The recycler view gets refreshed somehow when the positive button in the dialog is pressed even though I never call notifyItemInserted() or notifyDatasetChange() after passing the new input. I want to know how this happens, my guess is the recyclerview is somehow refreshed after the positive button is pressed in the dialog box
Custom AlertDialog Code:
public class CustomDialog extends AppCompatDialogFragment {
OnNoteAddedListener onNoteAddedListener;
public interface OnNoteAddedListener {
public void onClick(String note);
}
public CustomDialog(OnNoteAddedListener onNoteAddedListener) {
this.onNoteAddedListener = onNoteAddedListener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
final LayoutInflater inflater = getActivity().getLayoutInflater();
final View dialogLayout = inflater.inflate(R.layout.dialog_box, null);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(dialogLayout).setPositiveButton("Ok", new DialogInterface.OnClickListener() {#Override
public void onClick(DialogInterface dialog, int id) {
EditText addNote = dialogLayout.findViewById(R.id.note_text);
String note = addNote.getText().toString();
onNoteAddedListener.onClick(note);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
CustomDialog.this.getDialog().cancel();
}
});
return builder.create();
}
}
Adapter code:
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>
{
private static final String TAG = "RecyclerViewAdapter";
private List<String> notesList;
private Context mContext;
private SendPositionConnector sendPositionConnector;
public interface SendPositionConnector
{
public void sendPosition(int position);
}
public RecyclerViewAdapter(List<String> notesList, Context mContext)
{
this.notesList = notesList;
this.mContext = mContext;
this.sendPositionConnector = (MainActivity)mContext;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, final int position)
{
Log.d(TAG, "onBindViewHandler: called");
viewHolder.noteContent.setText(notesList.get(position));
viewHolder.parentLayout.setOnLongClickListener(new View.OnLongClickListener(){
#Override
public boolean onLongClick(View view)
{
Log.d(TAG, "onLongClick: long clicked on");
sendPositionConnector.sendPosition(position);
return false;
}
});
}
#Override
public int getItemCount()
{
return notesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView noteContent;
RelativeLayout parentLayout;
ImageView bullet;
public ViewHolder(#NonNull View itemView)
{
super(itemView);
bullet = itemView.findViewById(R.id.bullet);
noteContent = itemView.findViewById(R.id.text_content);
parentLayout = itemView.findViewById(R.id.parent_layout);
}
}
}
Activity Code:
public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.SendPositionConnector
{
private static final String TAG = "MainActivity";
private List<String> notesList = new ArrayList<>();
private RecyclerView recyclerView;
private RecyclerViewAdapter adapter;
private int position;
public AgentAsyncTask agentAsyncTask;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.my_recycler_view);
registerForContextMenu(recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
agentAsyncTask = new AgentAsyncTask(notesList, getApplicationContext(), true, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
adapter = new RecyclerViewAdapter(notesList, MainActivity.this);
recyclerView.setAdapter(adapter);
}
});
agentAsyncTask.execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.add_note:
showDialogBox(item);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onStop()
{
super.onStop();
new AgentAsyncTask(notesList, getApplicationContext(), false, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
}
}).execute();
}
#Override
protected void onDestroy()
{
super.onDestroy();
}
private boolean showDialogBox(MenuItem menuItem)
{
AppCompatDialogFragment dialogFragment = new CustomDialog(new CustomDialog.OnNoteAddedListener(){
#Override
public void onClick(String note)
{
Log.d(TAG, "onClick: "+ note);
notesList.add(note);
}
});
dialogFragment.show(getSupportFragmentManager(),"Adding");
return true;
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
#Override
public boolean onContextItemSelected(MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.delete:
notesList.remove(position);
adapter.notifyItemRemoved(position);
adapter.notifyItemRangeChanged(position, notesList.size());
return true;
default:
return false;
}
}
#Override
public void sendPosition(int position)
{
this.position = position;
}
private static class AgentAsyncTask extends AsyncTask<Void, Void, List<String>>
{
private List<String> notesList;
private boolean flag;
OnRead onRead;
Context context;
AppDataBase dataBase;
private static final String TAG = "AgentAsyncTask";
public interface OnRead
{
public void onRead(List<String> notesList);
}
private AgentAsyncTask(List<String> notesList,Context context,boolean flag, OnRead onRead)
{
this.notesList = notesList;
this.onRead = onRead;
this.flag = flag;
this.context = context;
}
#Override
protected List<String> doInBackground(Void... params)
{
dataBase = Room.databaseBuilder(context, AppDataBase.class, "database-name").build();
if(!flag)
{
Gson gson = new Gson();
Type type = new TypeToken<List<String>>() {}.getType();
String json = gson.toJson(notesList, type);
Log.d(TAG, "doInBackground: "+json);
Notes notes = new Notes();
notes.setNoteContent(json);
notes.setUid(1);
dataBase.notesDao().insertNotes(notes);
return notesList;
}
else
{
Gson gson = new Gson();
String notesListContent = dataBase.notesDao().getNotes();
if(dataBase.notesDao().getCount() != 0)
{
notesList = gson.fromJson(notesListContent, new TypeToken<List<String>>()
{
}.getType());
}
else
{
return notesList;
}
return notesList;
}
}
#Override
protected void onPostExecute(List<String> notesList)
{
super.onPostExecute(notesList);
if(flag)
onRead.onRead(notesList);
}
}
}
What's probably happening is that when the dialog returns, it causes a re-layout of the RecyclerView, which rebinds the views. This is prone to bugs though, since it may not have updated the recycler about stuff like the list length or item view types, etc, so the appropriate notify method should always be used.
When you get the text from the dialog to main activity after pressing the positive button.
Append your list with that new text that you are passing to adapter and call method
adapter.notifyDataSetChanged();

OnClickListener in PagerAdapter

I have an Activity that uses a ViewPager, within this ViewPager is a TouchImageView (an ImageView that detects gestures and zooms/moves accordingly).
Now I want to change some things in the UI whenever the image is clicked, but because the TouchImageView is declared in the PagerAdapter I can't reach it and if I would setup something on the side of the PagerAdapter I couldn't reach the UI components I want to change (I would also like to use the same adapter somewhere else in my app when I got this working). I've tried setting up an onClickListener on the ViewPager itself, but that doesn't trigger. Now I really don't know what to do.
Here is the adapter:
public class FullScreenImageAdapter extends PagerAdapter {
private ArrayList<MediaFile> images;
public FullScreenImageAdapter( ArrayList<MediaFile> images) {
this.images = images;
}
#Override
public int getCount() {
return images.size();
}
#Override
public View instantiateItem(ViewGroup container, int position) {
TouchImageView img = new TouchImageView(container.getContext());
Bitmap bitmap = BitmapFactory.decodeFile(images.get(position).getPath());
img.setImageBitmap(bitmap);
container.addView(img, ViewPager.LayoutParams.MATCH_PARENT, ViewPager.LayoutParams.MATCH_PARENT);
return img;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
And here is the method that interacts with it (in the ProjectOverviewActivity class):
private void viewPicture(final int position) {
View decorView = getWindow().getDecorView();
statusBarVisibility = decorView.getSystemUiVisibility();
// Hide the status bar.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
FullScreenImageAdapter imageAdapter = new FullScreenImageAdapter(mediaFiles);
final ViewPager viewPager = (ViewPager) findViewById(R.id.image_pager);
viewPager.setAdapter(imageAdapter);
viewPager.setCurrentItem(position);
View fancyBox = findViewById(R.id.fancyBox);
fancyBox.setVisibility(View.VISIBLE);
viewPager.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View btnClose = findViewById(R.id.fancyBoxBtnClose);
View btnPrev = findViewById(R.id.fancyBoxBtnPrev);
View btnNext = findViewById(R.id.fancyBoxBtnNext);
if (overlayButtonsVisible) {
btnClose.setVisibility(View.GONE);
btnPrev.setVisibility(View.GONE);
btnNext.setVisibility(View.GONE);
} else {
btnClose.setVisibility(View.VISIBLE);
if (viewPager.getCurrentItem() > 0) {
btnPrev.setVisibility(View.VISIBLE);
}
if (viewPager.getCurrentItem() < (mediaFiles.size() - 1)) {
btnNext.setVisibility(View.VISIBLE);
}
}
overlayButtonsVisible = !overlayButtonsVisible;
}
});
View fancyBoxBtnClose = findViewById(R.id.fancyBoxBtnClose);
final View fancyBoxBtnPrev = findViewById(R.id.fancyBoxBtnPrev);
final View fancyBoxBtnNext = findViewById(R.id.fancyBoxBtnNext);
fancyBoxBtnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View decorView = getWindow().getDecorView();
// Show the status bar.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
decorView.setSystemUiVisibility(statusBarVisibility);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, statusBarVisibility);
}
findViewById(R.id.fancyBox).setVisibility(View.GONE);
setViewAndChildrenEnabled(findViewById(R.id.layoutProjectOverview), true);
overlayButtonsVisible = false;
}
});
fancyBoxBtnPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
if (viewPager.getCurrentItem() == 0) {
fancyBoxBtnPrev.setVisibility(View.GONE);
}
}
});
fancyBoxBtnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
if (viewPager.getCurrentItem() == (mediaFiles.size() - 1)) {
fancyBoxBtnNext.setVisibility(View.GONE);
}
}
});
}
You can try this
Update:
I think you should create your custom ViewPager with GestureDetector
Example:
public class ClickableViewPager extends ViewPager {
private OnItemClickListener mOnItemClickListener;
public ClickableViewPager(Context context) {
super(context);
setup();
}
public ClickableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
private void setup() {
final GestureDetector tapGestureDetector = new GestureDetector(getContext(), new TapGestureListener());
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
tapGestureDetector.onTouchEvent(event);
return false;
}
});
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onItemClick(int position);
}
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if(mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(getCurrentItem());
}
return true;
}
}
}
and then in your activity
ClickableViewPager viewPager = (ClickableViewPager) findViewById(R.id.viewPager);
viewPager.setOnItemClickListener(new ClickableViewPager.OnItemClickListener() {
#Override
public void onItemClick(int position) {
// HADNLE YOUR CLICKS
}
});
SOURCE

How to refresh the fragment inside viewpager dynamically?

I have one ViewPager(mainViewPager) inside my MainActivity which renders from a fragment that contains another ViewPager(imageViewPager) and a TextView. Now The imageViewPager renders from another fragment that contains ImageView and a button. I've set onClick listener on this ImageView that turns in fullscreen view of the image with a button beneath.Now onClick of this buttton I want to return to my MainActivity with the condition to be on the same page from which I entered and with the same image which I viewed last in fullscreen.I am able to get the same page but the image always starts from 0.
Basically my hierarchy is like:
MainActivity
--mainViewPager-->TaskFragment
--imageViewPager-->ImageFragment(contains only ImageView
--TextView(set text returned from MainActivity)
My Code:
MainActivity.java
public class MainActivity extends FragmentActivity {
private ViewPager mViewPager;
private CustomPagerAdapter mPagerAdapter;
private int changedPosition;
private String[] vehicles = new String[]{"Audi Q7", "Honda Accord", "Hyundai i20", "Maruti Suzuki Swift", "Mahindra XUV 500",
"Swift Dzire", "Honda City", "Honda Civic", "Mercedez Benz", "Rolls Royce", "Ferrari"};
private String[][] vehicle_info = new String[][]{
{"http://www.hdwallpapers.in/walls/2010_abt_audi_q7_3_tdi_3-wide.jpg",
"http://www.hdwallpapers.in/walls/2010_mtm_audi_s5_cabrio_michelle_edition-wide.jpg",
"http://www.hdwallpapers.in/walls/2009_audi_tts_coupe_car-wide.jpg"},
{"http://automobiles.honda.com/images/2015/accord-sedan/exterior-gallery/2015-honda-accord-sedan-sport-exterior-side1.jpg",
"http://www.carprousa.com/wp-content/uploads/2015/01/HondaInterior-e1421978263126.jpg",
"http://www.carprousa.com/wp-content/uploads/2015/01/HondaInterior2-e1421978365916.jpg"},
...........
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager)findViewById(R.id.mainViewPager);
mPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager(), vehicles, vehicle_info);
mViewPager.setAdapter(mPagerAdapter);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
changedPosition = data.getIntExtra("CHANGED_POSITION", 0);
Log.i("POSITION 3:"," "+changedPosition);
TaskFragment fragment = new TaskFragment();
Bundle bundle = new Bundle();
bundle.putInt("IMAGE_POSITION", changedPosition);
fragment.setArguments(bundle);
}
}
}
activity_main.xml
<android.support.v4.view.ViewPager
android:id="#+id/mainViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
CustomPagerAdapter.java
public class CustomPagerAdapter extends FragmentStatePagerAdapter{
private String[] vehicles,selected_vehicle_info;
private String[][] vehicle_info;
public CustomPagerAdapter(FragmentManager fragmentManager,String[] vehicles,String[][] vehicle_info){
super(fragmentManager);
this.vehicles = vehicles;
this.vehicle_info = vehicle_info;
}
#Override
public Fragment getItem(int position) {
selected_vehicle_info = vehicle_info[position];
TaskFragment taskFragment = new TaskFragment();
Bundle bundle = new Bundle();
bundle.putString("ITEM",vehicles[position]);
bundle.putStringArray("ITEM_INFO",selected_vehicle_info);
taskFragment.setArguments(bundle);
return taskFragment;
}
#Override
public int getCount() {
return vehicles.length;
}
}
TaskFragment.java
public class TaskFragment extends Fragment {
private String vehicle;
private String[] vehicle_info;
private ViewPager imageViewPager;
private ImagePagerAdapter imagePagerAdapter;
private int changedImagePosition;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
vehicle = getArguments().getString("ITEM");
vehicle_info = getArguments().getStringArray("ITEM_INFO");
View view = inflater.inflate(R.layout.activity_task_fragment,container,false);
TextView messageTextView = (TextView) view.findViewById(R.id.textView);
messageTextView.setText(vehicle);
imageViewPager = (ViewPager)view.findViewById(R.id.imageViewPager);
imagePagerAdapter = new ImagePagerAdapter(getActivity(), vehicle_info);
imagePagerAdapter.notifyDataSetChanged();
imageViewPager.setAdapter(imagePagerAdapter);
imageViewPager.setCurrentItem(changedImagePosition);
return view;
}
private class ImagePagerAdapter extends PagerAdapter {
private Activity activity;
private String[] vehicle_info;
public ImagePagerAdapter(Activity activity,String[] vehicle_info){
this.activity = activity;
this.vehicle_info = vehicle_info;
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater = LayoutInflater.from(activity);
View view = inflater.inflate(R.layout.activity_image_fragment,container,false);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
Picasso.with(getContext()).load(vehicle_info[position]).into(imageView);
if(imageView.getParent()!=null)
((ViewGroup)imageView.getParent()).removeView(imageView);
((ViewPager) container).addView(imageView, 0);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(activity, ImageInFullScreen.class);
intent.putExtra("IMAGES_URL", vehicle_info);
intent.putExtra("IMAGE_POSITION", position);
activity.startActivityForResult(intent, 0);
}
});
return imageView;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return vehicle_info.length;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}
ImageInFullScreen.java
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent();
intent.putExtra("CHANGED_POSITION",changedImgPosition);
setResult(0,intent);}});
//and the same adapter n all.
where ever you want to refresh the view put the following code
this.page_position = 0;
imagePagerAdapter.notifyDataSetChanged();
and in your ImagePagerAdapter override the following function -
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
POSITION_NONE means whenever notifyDataSetChanged is called, adapter will create fresh views rather than using the same views.
This should work in our case.
I have found an answer to my question, the problem was that somehow my setCurrentItem() wasn't working inside TaskFragment's onCreateView(), so I've moved it to the Run method of Runnable interface's postAtTime()nd then it worked perfectly.
Here's my edited code.
MainActivity.java`
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
claim_id = vehicleDetailsArrayList.get(changedPage).getClaimId();
//Retrieve value of position of last viewed image, before clicking the button
changedPosition = data.getIntExtra("CHANGED_POSITION", 0);
Log.i("POSITION 3:"," "+changedPosition);
if(changedPage > -1 && changedPage < vehicleDetailsArrayList.size()) {
addUpdateImagePositionInList(claim_id, changedPosition);
}
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (mViewPager.getAdapter() != null) {
mViewPager.getAdapter().notifyDataSetChanged();
}
}
}, 0);
}
}
public void addUpdateImagePositionInList(int claimId, int position){
for (int imageLength = 0; imageLength < imagePositionArrayList.size(); imageLength++)
{
if (claimId == (imagePositionArrayList.get(imageLength).getClaim_id()))
{
imagePositionArrayList.get(imageLength).setImagePosition(position);
return;
}
}
imagePositionArrayList.add(new ImagePosition(claimId, position));
}
public int getChangedImagePosition(int claimId){
for (int imageLength = 0; imageLength < imagePositionArrayList.size(); imageLength++)
{
if (claimId == (imagePositionArrayList.get(imageLength).getClaim_id()))
{
Log.i("POSITION123 "," ::"+ imagePositionArrayList.get(imageLength).getImagePosition() );
return imagePositionArrayList.get(imageLength).getImagePosition();
}
}
return 0;
}
`
TaskFragment.java`
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
id = getArguments().getInt("ID");
vehicle = getArguments().getString("ITEM");
vehicle_info = getArguments().getStringArray("ITEM_INFO");
changedImagePosition = ((MainActivity)getActivity()).getChangedImagePosition(id);
View view = inflater.inflate(R.layout.task_fragment,container,false);
TextView messageTextView = (TextView) view.findViewById(R.id.textView);
messageTextView.setText(vehicle);
imageViewPager = (ViewPager)view.findViewById(R.id.imageViewPager);
imagePagerAdapter = new ImagePagerAdapter(getActivity(), vehicle_info);
imageViewPager.setAdapter(imagePagerAdapter);
/*The below code doesn't work
if (imageViewPager.getCurrentItem() != changedImagePosition) {
Log.i("POSITION current", ":" + imageViewPager.getCurrentItem());
Log.i("POSITION changed", " :"+ changedImagePosition);
setCurrentItem = true;
imageViewPager.setCurrentItem(changedImagePosition, false);
Log.i("POSITION getCurrent", " :" + imageViewPager.getCurrentItem());
}
*/
new Handler().postAtTime(new Runnable() {
#Override
public void run() {
if (imageViewPager.getAdapter() != null) {
imageViewPager.getAdapter().notifyDataSetChanged();
imageViewPager.setCurrentItem(changedImagePosition);
}
}
},0);
return view;
}
`

Null class variables implementing interface

I haven't found similar questions, so I'm writing a new one.
I'm developing a little Android app and I have some problems with an interface. The app consists of 3 fragments and a ViewPager. Clicking a button, I show a custom dialog (made my extending the AlertDialog.Builder class). To retrieve data back from the target fragment, I made an interface that I implement in the fragment.
Everything seems to work, but when I try to access fragment class variables inside the overridden methods, they are null! Class variables are initialized in onCreateView fragment method.
Thanks
import android.content.DialogInterface;
public interface BandDialogInterface{
public void onActionCreate(DialogInterface dialog, String name, MyColor color);
public void onActionEdit(DialogInterface dialog, int id, String name, MyColor color);
}
It's a bit messy because I was trying something:
public class EditBandDialog extends AlertDialog.Builder {
private final Band band;
private Spinner listColor;
private EditText inputName;
private DatabaseHelper dbHelper;
private BandDialogInterface bandDialogInterface;
public EditBandDialog(Context context, final Band band){
super(context);
this.band = band;
try{
bandDialogInterface = ((MercenAppActivity)context).getBandsFragment();
Log.d("CONTEXT", ((MercenAppActivity)context).getBandsFragment().toString());
}catch (Exception e){
e.printStackTrace();
}
View dialogView = ((Activity)context).getLayoutInflater().inflate(R.layout.dialog_edit_band, null);
setView(dialogView);
setCancelable(false);
dbHelper = new DatabaseHelper(context);
listColor = (Spinner)dialogView.findViewById(R.id.dialog_edit_band_color);
inputName = (EditText)dialogView.findViewById(R.id.dialog_edit_band_name);
BandColorAdapter adapter = new BandColorAdapter(context);
listColor.setAdapter(adapter);
if(isNewBand()) {
setTitle(R.string.title_new_band);
setPositiveButton("Crea", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//bandAdapter.insert(new Band(-1, inputName.getText().toString(), ((MyColor) listColor.getSelectedItem())));
//Toast.makeText(getContext(), R.string.toast_band_added, Toast.LENGTH_SHORT).show();
bandDialogInterface.onActionCreate(dialog, inputName.getText().toString(), (MyColor)listColor.getSelectedItem());
}
});
}else{
setTitle(R.string.title_edit_band);
inputName.setText(band.getName());
int pos = 0;
while(((MyColor)listColor.getAdapter().getItem(pos)).getColor() != band.getColor())
pos++;
listColor.setSelection(pos);
setPositiveButton("Modifica", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//dbHelper.updateBand(dbHelper.getWritableDatabase(), band.getId(), inputName.getText().toString(), ((MyColor) listColor.getSelectedItem()).getColor());
//bandAdapter.update(new Band(band.getId(), inputName.getText().toString(), ((MyColor) listColor.getSelectedItem())));
//Toast.makeText(getContext(), R.string.toast_band_edited, Toast.LENGTH_SHORT).show();
bandDialogInterface.onActionEdit(dialog, band.getId(), inputName.getText().toString(), (MyColor)listColor.getSelectedItem());
}
});
}
setNegativeButton("Annulla", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
}
private boolean isNewBand(){
return band == null;
}
}
class MyColor{
int color;
public MyColor(int color){
this.color = color;
}
public static MyColor fromString(String s){
return new MyColor(Color.parseColor(s));
}
public int getColor(){
return color;
}
}
class BandColorAdapter extends ArrayAdapter<MyColor> implements SpinnerAdapter {
private static final MyColor[] colors = {MyColor.fromString("#D60000"), //ROSSO
MyColor.fromString("#0080FF"), //AZZURRO
MyColor.fromString("#00AD37"), //VERDE
MyColor.fromString("#FFF700"), //GIALLO
MyColor.fromString("#FF8400"), //ARANCIO
MyColor.fromString("#10009C")}; //BLU
public BandColorAdapter(Context context) {
super(context, R.layout.row_band_color, colors);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_band_color, parent, false);
}
View bandColor = convertView.findViewById(R.id.band_color_item);
bandColor.setBackgroundColor(getItem(position).getColor());
return convertView;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_band_color, parent, false);
}
View bandColor = convertView.findViewById(R.id.band_color_item);
bandColor.setBackgroundColor(getItem(position).getColor());
return convertView;
}
}
And this is the class where I implement the interface:
public class BandsFragment extends Fragment implements BandDialogInterface{
private static final String TAG = "BandsFragment";
private static final boolean D = true;
private DatabaseHelper dbHelper;
private BandAdapter bandAdapter;
private String s;
public BandsFragment(){
}
#Override
public void onActionCreate(DialogInterface dialog, String name, MyColor color) {
//Toast.makeText(getActivity(), "CREATE", Toast.LENGTH_SHORT).show();
//bandAdapter.insert(new Band(0, name, color));
Log.d("CREATE", s);
}
#Override
public void onActionEdit(DialogInterface dialog, int id, String name, MyColor color) {
Toast.makeText(getActivity(), "EDITED", Toast.LENGTH_SHORT).show();
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static BandsFragment newInstance() {
BandsFragment fragment = new BandsFragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_bands, container, false);
if (D) Log.d(TAG, "--- onCreateView ---");
dbHelper = new DatabaseHelper(getActivity());
ListView listBands = (ListView)rootView.findViewById(R.id.list_bands);
TextView noBands = (TextView)rootView.findViewById(R.id.no_bands);
bandAdapter = new BandAdapter(getActivity(), noBands);
listBands.setAdapter(bandAdapter);
// if(dbList.size() == 0){
// noBands.setVisibility(View.VISIBLE);
// }else{
// noBands.setVisibility(View.GONE);
// }
listBands.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//TODO something
}
});
registerForContextMenu(listBands);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (D) Log.d(TAG, "--- onAttach ---");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (D) Log.d(TAG, "--- onCreate ---");
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (D) Log.d(TAG, "--- onViewCreated ---");
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (D) Log.d(TAG, "--- onActivityCreated ---");
}
#Override
public void onStart() {
super.onStart();
if (D) Log.d(TAG, "--- onStart ---");
}
#Override
public void onResume() {
super.onResume();
if (D) Log.d(TAG, "--- onResume ---");
}
#Override
public void onPause() {
super.onPause();
if (D) Log.d(TAG, "--- onPause ---");
}
#Override
public void onStop() {
super.onStop();
if (D) Log.d(TAG, "--- onStop ---");
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (D) Log.d(TAG, "--- onDestroyView ---");
}
#Override
public void onDestroy() {
super.onDestroy();
if (D) Log.d(TAG, "--- onDestroy ---");
}
#Override
public void onDetach() {
super.onDetach();
if (D) Log.d(TAG, "--- onDetach ---");
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderTitle(bandAdapter.getItem(info.position).getName());
getActivity().getMenuInflater().inflate(R.menu.context_band, menu);
MenuItem.OnMenuItemClickListener l = new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
onContextItemSelected(item);
return true;
}
};
for(int i = 0; i < menu.size(); ++i){
menu.getItem(i).setOnMenuItemClickListener(l);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
switch (item.getItemId()){
case R.id.context_band_edit:
new EditBandDialog(getActivity(), bandAdapter.getItem(info.position)).show();
//Log.d("D",bandAdapter.getItem(info.position).getName());
break;
case R.id.context_band_delete:
/*dbHelper.deleteBand(dbHelper.getWritableDatabase(), bandAdapter.getItem(info.position).getId());
bandAdapter.remove(bandAdapter.getItem(info.position));
bandAdapter.notifyDataSetChanged();*/
bandAdapter.delete(bandAdapter.getItem(info.position));
Toast.makeText(getActivity(), R.string.toast_band_deleted, Toast.LENGTH_SHORT).show();
break;
}
return true;
}
}
class BandAdapter extends ArrayAdapter<Band> implements SpinnerAdapter{
private DatabaseHelper dbHelper;
private TextView noBands;
public BandAdapter(Context context, TextView noBands) {
super(context, R.layout.row_band);
this.noBands = noBands;
dbHelper = new DatabaseHelper(context);
updateAdapter();
}
private void updateAdapter(){
clear();
addAll(dbHelper.getAllBands());
if(noBands != null) {
if (isEmpty()) {
noBands.setVisibility(View.VISIBLE);
} else {
noBands.setVisibility(View.GONE);
}
}
notifyDataSetChanged();
}
public void insert(Band band){
//dbHelper.insertBand(dbHelper.getWritableDatabase(), band.getName(), band.getColor());
Toast.makeText(getContext(), "ADDED", Toast.LENGTH_SHORT).show();
updateAdapter();
}
public void update(Band band){
dbHelper.updateBand(dbHelper.getWritableDatabase(), band.getId(), band.getName(), band.getColor());
updateAdapter();
}
public void delete(Band band){
dbHelper.deleteBand(dbHelper.getWritableDatabase(), band.getId());
updateAdapter();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Band band = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_band, parent, false);
}
// Lookup view for data population
TextView bandName = (TextView) convertView.findViewById(R.id.band_name);
View bandColor = (View) convertView.findViewById(R.id.band_color);
bandColor.setBackgroundColor(band.getColor());
// Populate the data into the template view using the data object
bandName.setText(band.getName());
// Return the completed view to render on screen
return convertView;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_band, parent, false);
}
Band band = getItem(position);
TextView bandName = (TextView) convertView.findViewById(R.id.band_name);
View bandColor = (View) convertView.findViewById(R.id.band_color);
bandColor.setBackgroundColor(band.getColor());
// Populate the data into the template view using the data object
bandName.setText(band.getName());
return convertView;
}
}

Categories

Resources