clickable string array items inside each recycleview item - java

I have an API which have data like this:
{"seasons":[
{
"id":"1",
"titles":"1title1;1title2;1title3",
"url":"1url1;1url2;1url3;"
},
{
"id":"2",
"titles":"2title1;2title2;2title3",
"url":"2url1;2url2;2url3;"
}
]}
I parse it well and in parcelable class I did this for titles:
public String getTitles() {
return titles;
}
public StringBuilder getFullTitles() {
StringBuilder builder = new StringBuilder();
String[] titlesArray = getTitles().split(";");
for (String title : titlesArray) {
builder.append(title + "\n");
}
and this for url:
public String getUrlAdaptive() {
return urladaptive;
}
public StringBuilder getFullUrlAdaptiveFinal() {
StringBuilder builder2 = new StringBuilder();
String[] urlArray = getUrlAdaptive().split(";");
for (String details : urlArray) {
builder2.append(details + "\n");
}
return builder2;
}
so in my recycleview adapter I fetch titles data like this in textview:
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.title.setText(String.valueOf(mMoviesItems.get(position).getFullTitles()));
}
and the result that I got in my recycleview app is like this:
1title1
1title2
1title3
2title1
2title2
2title3
now you can see that this group:
1title1
1title2
1title3
refer to the first item of recycleview
and this group:
2title1
2title2
2title3
refer to the second item of recycleview
you can compare it with api to understand what I mean
what I need to do is to make each item of each group is applicable to be clicked
like when I click on 1title1 I got the url that correspond the title which is 1url1 to open it in youtube
and when I click on 1title2 I got the url that correspond the title which is 1url2 to open it in youtube
and when I click on 2title2 I got the url that correspond the title which is 2url2 to open it in youtube
and so on
it's like click items inside each of main item of recycleview
this is the code after try an answer:
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position) {
holder.title.setText(String.valueOf(mMoviesItems.get(position).getFullTitles()));
holder.title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View vview) {
// here when click on each title I need to get the getFullUrlAdaptiveFinal with it to play it
}
});
}
and this is full code for series_list_item.xml:
<?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="wrap_content"
android:background="#21293B"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:textSize="14sp"
android:visibility="visible" />
<TextView
android:id="#+id/url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:textSize="14sp"
android:visibility="visible" />
</LinearLayout>
Adapter Code:
public class SeriesAdapter extends RecyclerView.Adapter<SeriesAdapter.RecyclerViewHolder> {
ArrayList<SeriesItem> mMoviesItems;
private Context context;
private SeriesAdapterOnClickHandler mClickHandler;
public interface SeriesAdapterOnClickHandler {
void onClick(SeriesItem movie);
}
public SeriesAdapter(SeriesAdapterOnClickHandler clickHandler) {
mClickHandler = clickHandler;
}
public void setClickListener(SeriesAdapterOnClickHandler callback) {
mClickHandler = callback;
}
class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView SeriesSeasontitle;
public final TextView urlAdaptive;
public RecyclerViewHolder(View view) {
super(view);
SeriesSeasontitle = (TextView)itemView.findViewById(R.id.title);
urlAdaptive = (TextView)itemView.findViewById(R.id.url);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
SeriesItem movie = mMoviesItems.get(adapterPosition);
String text = "already Added To Favorites";
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
mClickHandler.onClick(movie);
}
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
context = viewGroup.getContext();
int layoutIdForListItem = R.layout.series_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
RecyclerViewHolder holder = new RecyclerViewHolder(view);
return new RecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position) {
holder.SeriesSeasontitle.setText(String.valueOf(mMoviesItems.get(position).getFullTitles()));
holder.SeriesSeasontitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View vview) {
String text = "text";
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
if (null == mMoviesItems)
return 0;
else {
return mMoviesItems.size();
}
}
#Override
public int getItemViewType(int position) {
if (null == mMoviesItems)
return 0;
else {
return mMoviesItems.size();
}
}
public void setMovieData(ArrayList<SeriesItem> movieData) {
mMoviesItems = movieData;
notifyDataSetChanged();
}
}
Activity code:
SeriesDetail extends AppCompatActivity implements
SeriesAdapter.SeriesAdapterOnClickHandler {
SeriesAdapter mAdapterTrailer;
RecyclerViewAdapterOthers mAdapterOthers;
#BindView(R.id.rv_videos)
RecyclerView mVideosList;
#BindView(R.id.tv_error_message_display3)
TextView mErrorMessageDisplay3;
#BindView(R.id.rv_videos2)
RecyclerView mTrailersList;
#BindView(R.id.pb_loading_indicator_trailers2)
ProgressBar mLoadingIndicatorTrailers2;
String sortOrder2="seasons/1435";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_series_detail);
ButterKnife.bind(this);
LinearLayoutManager LayoutManager2 = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mTrailersList.setLayoutManager(LayoutManager2);
mTrailersList.setHasFixedSize(true);
mAdapterTrailer = new SeriesAdapter(this);
mTrailersList.setAdapter(mAdapterTrailer);
loadVideosData(String.valueOf(sortOrder2));
}
private void loadVideosData(String movieId) {
showVideoDataView();
new FetchVideosTask().execute(movieId);
}
#Override
public void onClick(SeriesItem video) {
}
private void showTrailerDataView() {
mErrorMessageDisplay3.setVisibility(View.INVISIBLE);
mTrailersList.setVisibility(View.VISIBLE);
}
private void showErrorMessage3() {
mTrailersList.setVisibility(View.INVISIBLE);
mErrorMessageDisplay3.setVisibility(View.VISIBLE);
}
public class FetchVideosTask extends AsyncTask<String, Void, ArrayList<SeriesItem>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mLoadingIndicatorTrailers2.setVisibility(View.VISIBLE);
}
#Override
protected ArrayList<SeriesItem> doInBackground(String... params) {
if (params.length == 0) {
return null;
}
String movieId = params[0];
URL videosRequestUrl = NetworkSeries.buildUrl(movieId);
try {
String jsonVideoResponse = NetworkSeries.getResponseFromHttpUrl(videosRequestUrl);
ArrayList<SeriesItem> simpleJsonVideoData = JsonShashaDetailSeries.getSimpleMovieStringsFromJson(SeriesDetail.this, jsonVideoResponse);
return simpleJsonVideoData;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(ArrayList<SeriesItem> videoData) {
mLoadingIndicatorTrailers2.setVisibility(View.INVISIBLE);
if (videoData != null) {
showTrailerDataView();
mAdapterTrailer.setMovieData(videoData);
} else {
showErrorMessage3();
}
}
}
#Override
protected void onStart() {
super.onStart();
}
}
and parcalable class:
public class SeriesItem implements Parcelable {
private String titles;
private String urladaptive;
public SeriesItem(String titles, String urladaptive) {
this.titles = titles;
this.urladaptive = urladaptive;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(titles);
out.writeString(urladaptive);
}
private SeriesItem(Parcel in) {
this.titles = in.readString();
this.urladaptive = in.readString();
}
public SeriesItem() {
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SeriesItem> CREATOR = new Creator<SeriesItem>() {
#Override
public SeriesItem createFromParcel(Parcel in) {
return new SeriesItem(in);
}
#Override
public SeriesItem[] newArray(int i) {
return new SeriesItem[i];
}
};
public String getTitles() {
return titles;
}
public StringBuilder getFullTitles() {
StringBuilder builder = new StringBuilder();
String[] titlesArray = getTitles().split(";");
for (String details : titlesArray) {
builder.append(details + "\n");
}
return builder;
}
public String getUrlAdaptive() {
return urladaptive;
}
public StringBuilder getFullUrlAdaptiveFinal() {
StringBuilder builder2 = new StringBuilder();
String[] urlArray = getUrlAdaptive().split(";");
for (String details : urlArray) {
builder2.append(details + "\n");
}
return builder2;
}
}
I just try to display a toast message when onclick the above code to test the click of items and it work
but if I would like when I click on title like now so the url of same item start play
how I handle this click? in adapter itself or in activity?

Yes this is possible. Simply use an OnClickListener and set it in your onBindViewHolder().
It would look something like this:
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.title.setText(String.valueOf(mMoviesItems.get(position).getFullTitles()));
holder.title.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// Toast here
}
}
}

Related

View null on accessing from inner class : Fragment

I have taken youtube-api sample app VideoListDemoActivity class for android and converted it to fragment to use in my app.
In inner class VideoListFragment the view videoBox from fragment is accessed, which returns null. In activity the view is not null but in fragment it's failing to get reference of fragment's view. I have attached code which I modified for this class.
Error Exception
2021-04-28 16:42:18.695 27495-27495/com.gardify.android
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gardify.android, PID: 27495
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getVisibility()' on a null object reference
at com.gardify.android.ui.video.VideoFragment$VideoListFragment.onListItemClick(VideoFragment.java:192)
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
videoBox = getView().findViewById(R.id.video_box);
^^^^^^^^
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListAdapter(adapter);
}
modified Class
public final class VideoFragment extends Fragment {
/**
* The duration of the animation sliding up the video in portrait.
*/
private static final int ANIMATION_DURATION_MILLIS = 300;
/**
* The padding between the video list and the video in landscape orientation.
*/
private static final int LANDSCAPE_VIDEO_PADDING_DP = 5;
/**
* The request code when calling startActivityForResult to recover from an API service error.
*/
private static final int RECOVERY_DIALOG_REQUEST = 1;
private VideoListFragment listFragment;
private YoutubeFragment videoFragment;
private View videoBox;
private View closeButton;
private View root;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.video_fragment, container, false);
videoBox = root.findViewById(R.id.video_box);
closeButton = root.findViewById(R.id.close_button);
videoBox.setVisibility(View.INVISIBLE);
return root;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listFragment = (VideoListFragment) getActivity().getFragmentManager().findFragmentById(R.id.list_fragment);
videoFragment = (YoutubeFragment) getActivity().getFragmentManager().findFragmentById(R.id.video_fragment_container);
checkYouTubeApi();
}
private void checkYouTubeApi() {
YouTubeInitializationResult errorReason =
YouTubeApiServiceUtil.isYouTubeApiServiceAvailable(getActivity());
if (errorReason.isUserRecoverableError()) {
errorReason.getErrorDialog(getActivity(), RECOVERY_DIALOG_REQUEST).show();
} else if (errorReason != YouTubeInitializationResult.SUCCESS) {
String errorMessage = getResources().getString(R.string.an_error_occurred);
Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECOVERY_DIALOG_REQUEST) {
// Recreate the activity if user performed a recovery action
getActivity().recreate();
}
}
public void onClickClose(#SuppressWarnings("unused") View view) {
listFragment.getListView().clearChoices();
listFragment.getListView().requestLayout();
videoFragment.pause();
ViewPropertyAnimator animator = videoBox.animate()
.translationYBy(videoBox.getHeight())
.setDuration(ANIMATION_DURATION_MILLIS);
runOnAnimationEnd(animator, new Runnable() {
#Override
public void run() {
videoBox.setVisibility(View.INVISIBLE);
}
});
}
#TargetApi(16)
private void runOnAnimationEnd(ViewPropertyAnimator animator, final Runnable runnable) {
if (Build.VERSION.SDK_INT >= 16) {
animator.withEndAction(runnable);
} else {
animator.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
runnable.run();
}
});
}
}
/**
* A fragment that shows a static list of videos.
*/
public static final class VideoListFragment extends ListFragment {
private static final List<VideoEntry> VIDEO_LIST;
static {
List<VideoEntry> list = new ArrayList<VideoEntry>();
list.add(new VideoEntry("YouTube Collection", "Y_UmWdcTrrc"));
list.add(new VideoEntry("GMail Tap", "1KhZKNZO8mQ"));
list.add(new VideoEntry("Chrome Multitask", "UiLSiqyDf4Y"));
list.add(new VideoEntry("Google Fiber", "re0VRK6ouwI"));
list.add(new VideoEntry("Autocompleter", "blB_X38YSxQ"));
list.add(new VideoEntry("GMail Motion", "Bu927_ul_X0"));
list.add(new VideoEntry("Translate for Animals", "3I24bSteJpw"));
VIDEO_LIST = Collections.unmodifiableList(list);
}
private PageAdapter adapter;
private View videoBox;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adapter = new PageAdapter(getActivity(), VIDEO_LIST);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
videoBox = getView().findViewById(R.id.video_box);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
String videoId = VIDEO_LIST.get(position).videoId;
YoutubeFragment videoFragment = (YoutubeFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
videoFragment.setVideoId(videoId);
// The videoBox is INVISIBLE if no video was previously selected, so we need to show it now.
if (videoBox.getVisibility() != View.VISIBLE) {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Initially translate off the screen so that it can be animated in from below.
videoBox.setTranslationY(videoBox.getHeight());
}
videoBox.setVisibility(View.VISIBLE);
}
// If the fragment is off the screen, we animate it in.
if (videoBox.getTranslationY() > 0) {
videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS);
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
adapter.releaseLoaders();
}
public void setLabelVisibility(boolean visible) {
adapter.setLabelVisibility(visible);
}
}
/**
* Adapter for the video list. Manages a set of YouTubeThumbnailViews, including initializing each
* of them only once and keeping track of the loader of each one. When the ListFragment gets
* destroyed it releases all the loaders.
*/
private static final class PageAdapter extends BaseAdapter {
private final List<VideoEntry> entries;
private final List<View> entryViews;
private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap;
private final LayoutInflater inflater;
private final ThumbnailListener thumbnailListener;
private boolean labelsVisible;
public PageAdapter(Context context, List<VideoEntry> entries) {
this.entries = entries;
entryViews = new ArrayList<View>();
thumbnailViewToLoaderMap = new HashMap<YouTubeThumbnailView, YouTubeThumbnailLoader>();
inflater = LayoutInflater.from(context);
thumbnailListener = new ThumbnailListener();
labelsVisible = true;
}
public void releaseLoaders() {
for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) {
loader.release();
}
}
public void setLabelVisibility(boolean visible) {
labelsVisible = visible;
for (View view : entryViews) {
view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
#Override
public int getCount() {
return entries.size();
}
#Override
public VideoEntry getItem(int position) {
return entries.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
VideoEntry entry = entries.get(position);
// There are three cases here
if (view == null) {
// 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView.
view = inflater.inflate(R.layout.video_list_item, parent, false);
YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
thumbnail.setTag(entry.videoId);
thumbnail.initialize(DeveloperKey.YOUTUBE_API_DEVELOPER_KEY, thumbnailListener);
} else {
YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail);
if (loader == null) {
// 2) The view is already created, and is currently being initialized. We store the
// current videoId in the tag.
thumbnail.setTag(entry.videoId);
} else {
// 3) The view is already created and already initialized. Simply set the right videoId
// on the loader.
//thumbnail.setImageResource(R.drawable.loading_thumbnail);
loader.setVideo(entry.videoId);
}
}
TextView label = ((TextView) view.findViewById(R.id.text));
label.setText(entry.text);
label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE);
return view;
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
thumbnailViewToLoaderMap.put(view, loader);
view.setImageResource(R.drawable.loading_thumbnail);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
public static final class YoutubeFragment extends YouTubePlayerFragment
implements OnInitializedListener {
private YouTubePlayer player;
private String videoId;
public static YoutubeFragment newInstance() {
return new YoutubeFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialize(DeveloperKey.YOUTUBE_API_DEVELOPER_KEY, this);
}
#Override
public void onDestroy() {
if (player != null) {
player.release();
}
super.onDestroy();
}
public void setVideoId(String videoId) {
if (videoId != null && !videoId.equals(this.videoId)) {
this.videoId = videoId;
if (player != null) {
player.cueVideo(videoId);
}
}
}
public void pause() {
if (player != null) {
player.pause();
}
}
#Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean restored) {
this.player = player;
}
#Override
public void onInitializationFailure(Provider provider, YouTubeInitializationResult result) {
this.player = null;
}
}
private static final class VideoEntry {
private final String text;
private final String videoId;
public VideoEntry(String text, String videoId) {
this.text = text;
this.videoId = videoId;
}
}
}
modified xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
class="com.gardify.android.ui.video.VideoFragment$VideoListFragment"
android:id="#+id/list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:id="#+id/video_box"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
<ImageButton
android:id="#+id/close_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#android:drawable/btn_dialog"
android:onClick="onClickClose"/>
<fragment
class="com.gardify.android.ui.video.VideoFragment$YoutubeFragment"
android:id="#+id/video_fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

How to fix 'java.lang.ClassCastException: Activity must implement fragment's callbacks'

I am a beginner who am writing a code that consists of two activities. Both have their own Fragments. On the first activity (in its fragment), the user input some fields. The result will be displayed on the second activity (in its list fragment).
I have tried to get state manually using bundle. And now, I am using callback to do that. However, I got an error message java.lang.ClassCastException: Activity must implement fragment's callbacks.
The first activity is:
public class AssetRegistrationInfoPage extends Page {
public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";
public static final String ASSET_ID_DATA_KEY = "assetID";
public static final String PROJECT_CODE_DATA_KEY = "projectCode";
public static final String REMARK_DATA_KEY = "remark";
public AssetRegistrationInfoPage(ModelCallbacks callbacks, String title) {
super(callbacks, title);
}
#Override
public Fragment createFragment() {
return AssetRegistrationInfoFragment.create(getKey());
}
#Override
public void getReviewItems(ArrayList<ReviewItem> dest) {
dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
dest.add(new ReviewItem("Kode Asset", mData. getString(ASSET_ID_DATA_KEY), getKey(), 0, null));
dest.add(new ReviewItem("Kode Project", mData.getString(PROJECT_CODE_DATA_KEY), getKey(),0,null));
dest.add(new ReviewItem("Kondisi Asset", mData.getString(REMARK_DATA_KEY), getKey(), 0, null));
}
#Override
public boolean isCompleted() {
return (!TextUtils.isEmpty(mData.getString(ASSET_TYPE_NAME_KEY)) &&
!TextUtils.isEmpty(mData.getString(ASSET_ID_DATA_KEY)) &&
!TextUtils.isEmpty(mData.getString(PROJECT_CODE_DATA_KEY)) &&
!TextUtils.isEmpty(mData.getString(REMARK_DATA_KEY)));
}
}
The first fragment:
public class AssetRegistrationInfoFragment extends Fragment {
private static final String ARG_KEY = "key";
private PageFragmentCallbacks mCallbacks;
private String mKey;
private AssetRegistrationInfoPage mPage;
private TextView mAssetID;
private AutoCompleteTextView mAssetTypeName, mProjectCode;
private TextView mRemark;
private Button mTakePicture;
static final int REQUEST_PICTURE_CAPTURE = 1;
private String pictureFilePath;
Bitmap bitmap;
ImageView mImgView;
ArrayList<String> projectCodes = new ArrayList<String>();
ArrayList<String> assetTypeNames = new ArrayList<String>();
public static AssetRegistrationInfoFragment create(String key) {
Bundle args = new Bundle();
args.putString(ARG_KEY, key);
AssetRegistrationInfoFragment fragment = new AssetRegistrationInfoFragment();
fragment.setArguments(args);
return fragment;
}
public AssetRegistrationInfoFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mKey = args.getString(ARG_KEY);
mPage = (AssetRegistrationInfoPage) mCallbacks.onGetPage(mKey);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
boolean cancel = false;
mAssetTypeName.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mAssetID.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mProjectCode.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mRemark.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.REMARK_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_asset_registration_info, container, false);
((TextView) view.findViewById(android.R.id.title)).setText(mPage.getTitle());
getAssetType();
mAssetTypeName = ((AutoCompleteTextView) view.findViewById(R.id.assetTypeName));
mAssetTypeName.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY));
ArrayAdapter<String> assetTypeNameAdapter = new ArrayAdapter<String>
(getActivity(), android.R.layout.simple_dropdown_item_1line, assetTypeNames);
mAssetTypeName.setAdapter(assetTypeNameAdapter);
mAssetID = ((TextView) view.findViewById(R.id.assetID));
mAssetID.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY));
getProjects();
mProjectCode = ((AutoCompleteTextView) view.findViewById(R.id.projectCode));
mProjectCode.setText(mPage.getData().getString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY));
mProjectCode.setThreshold(1);
ArrayAdapter<String> projectCodeAdapter = new ArrayAdapter<String>
(getActivity(), android.R.layout.simple_dropdown_item_1line, projectCodes);
mProjectCode.setAdapter(projectCodeAdapter);
mRemark = ((TextView) view.findViewById(R.id.remark));
mRemark.setText(mPage.getData().getString(AssetRegistrationInfoPage.REMARK_DATA_KEY));
return view;
}
private void getProjects() {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<Project>> call = apiService.getProjects("");
call.enqueue(new Callback<List<Project>>() {
#Override
public void onResponse(Call<List<Project>> call, Response<List<Project>> response) {
for (Project project : response.body()) {
projectCodes.add(project.getProjectCode());
}
}
#Override
public void onFailure(Call<List<Project>> call, Throwable t) {
Toast.makeText(getActivity(), "Unable to fetch Data " , Toast.LENGTH_LONG).show();
}
});
}
private void getAssetType() {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<AssetType>> call = apiService.getAssetTypes("");
call.enqueue(new Callback<List<AssetType>>() {
#Override
public void onResponse(Call<List<AssetType>> call, Response<List<AssetType>> response) {
for (AssetType assetType : response.body()) {
assetTypeNames.add(assetType.getName());
}
}
#Override
public void onFailure(Call<List<AssetType>> call, Throwable t) {
Toast.makeText(getActivity(), "Unable to fetch Data ", Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof PageFragmentCallbacks)) {
throw new ClassCastException("Activity must implement PageFragmentCallbacks");
}
mCallbacks = (PageFragmentCallbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
// In a future update to the support library, this should override setUserVisibleHint
// instead of setMenuVisibility.
if ( mAssetTypeName != null && mAssetID != null && mProjectCode != null && mRemark != null){
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE);
if (!menuVisible) {
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
}
}
}
The second page
public class AssetRegConfirmationPage extends Page {
public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";
public AssetRegConfirmationPage(ModelCallbacks callbacks, String title) {
super(callbacks, title);
}
#Override
public Fragment createFragment() {
return AssetRegConfirmationFragment.create(getKey());
}
#Override
public void getReviewItems(ArrayList<ReviewItem> dest) {
dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
}
}
The second fragment
public class AssetRegConfirmationFragment extends ListFragment implements ModelCallbacks {
private static final String ARG_KEY = "key";
private Callbacks mCallbacks;
private AbstractWizardModel mWizardModel;
private List<ReviewItem> mCurrentReviewItems;
private ReviewAdapter mReviewAdapter;
public AssetRegConfirmationFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReviewAdapter = new ReviewAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page, container, false);
TextView titleView = (TextView) rootView.findViewById(android.R.id.title);
titleView.setText(R.string.review);
titleView.setTextColor(getResources().getColor(R.color.colorPrimaryOld));
ListView listView = (ListView) rootView.findViewById(android.R.id.list);
setListAdapter(mReviewAdapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof Callbacks)) {
throw new ClassCastException("Activity must implement fragment's callbacks");
}
mCallbacks = (Callbacks) activity;
mWizardModel = mCallbacks.onGetModel();
mWizardModel.registerListener(this);
onPageTreeChanged();
}
#Override
public void onPageTreeChanged() {
onPageDataChanged(null);
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
mWizardModel.unregisterListener(this);
}
#Override
public void onPageDataChanged(Page changedPage) {
ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
for (Page page : mWizardModel.getCurrentPageSequence()) {
page.getReviewItems(reviewItems);
}
Collections.sort(reviewItems, new Comparator<ReviewItem>() {
#Override
public int compare(ReviewItem a, ReviewItem b) {
return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0;
}
});
mCurrentReviewItems = reviewItems;
if (mReviewAdapter != null) {
mReviewAdapter.notifyDataSetInvalidated();
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCallbacks.onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey());
}
public interface Callbacks {
AbstractWizardModel onGetModel();
void onEditScreenAfterReview(String pageKey);
}
private class ReviewAdapter extends BaseAdapter {
#Override
public boolean hasStableIds() {
return true;
}
#Override
public int getItemViewType(int position) {
return 0;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return true;
}
#Override
public Object getItem(int position) {
return mCurrentReviewItems.get(position);
}
#Override
public long getItemId(int position) {
return mCurrentReviewItems.get(position).hashCode();
}
#Override
public View getView(int position, View view, ViewGroup container) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
View rootView = inflater.inflate(R.layout.list_item_review, container, false);
ReviewItem reviewItem = mCurrentReviewItems.get(position);
String value = reviewItem.getDisplayValue();
if (TextUtils.isEmpty(value)) {
value = "(None)";
}
((TextView) rootView.findViewById(android.R.id.text1)).setText(reviewItem.getTitle());
((TextView) rootView.findViewById(android.R.id.text2)).setText(value);
return rootView;
}
#Override
public int getCount() {
return mCurrentReviewItems.size();
}
}
public static AssetRegConfirmationFragment create(String key) {
Bundle args = new Bundle();
args.putString(ARG_KEY, key);
AssetRegConfirmationFragment fragment = new AssetRegConfirmationFragment();
fragment.setArguments(args);
return fragment;
}
}
I have no idea of what should I do to make this work.
Here is the Page source code:
public abstract class Page implements PageTreeNode {
/**
* The key into {#link #getData()} used for wizards with simple (single) values.
*/
public static final String SIMPLE_DATA_KEY = "_";
protected ModelCallbacks mCallbacks;
/**
* Current wizard values/selections.
*/
protected Bundle mData = new Bundle();
protected String mTitle;
protected boolean mRequired = false;
protected String mParentKey;
protected Page(ModelCallbacks callbacks, String title) {
mCallbacks = callbacks;
mTitle = title;
}
public Bundle getData() {
return mData;
}
public String getTitle() {
return mTitle;
}
public boolean isRequired() {
return mRequired;
}
void setParentKey(String parentKey) {
mParentKey = parentKey;
}
#Override
public Page findByKey(String key) {
return getKey().equals(key) ? this : null;
}
#Override
public void flattenCurrentPageSequence(ArrayList<Page> dest) {
dest.add(this);
}
public abstract Fragment createFragment();
public String getKey() {
return (mParentKey != null) ? mParentKey + ":" + mTitle : mTitle;
}
public abstract void getReviewItems(ArrayList<ReviewItem> dest);
public boolean isCompleted() {
return true;
}
public Bitmap getPicture() {
return mData.getParcelable(getKey() + "_" + getTitle().trim());
}
public void resetData(Bundle data) {
mData = data;
notifyDataChanged();
}
public void notifyDataChanged() {
mCallbacks.onPageDataChanged(this);
}
public Page setRequired(boolean required) {
mRequired = required;
return this;
}
}
Look at this code in second fragment:
if (!(activity instanceof Callbacks)) {
throw new ClassCastException("Activity must implement fragment's callbacks");
}
Your activity where you using second fragment should implement Callbacks interface, like:
class YourActivity implements Callbacks {
}

How to filter data in a recycler view

I am fetching data from a server in a recycler view.In a layout file I have an EditText field on top and below it I have a recycler view.
I want to filter data based on what I have written in EditText field.
My problem is as I start typing in EditText field it shows no data in recycler and as I removes everything in EditText field it shows everything.
Why it is happening even if I have data present in recycler view with the same name I have entered in EditText field.
This is my code below:
Home.java
public class Home extends Fragment {
String myValue;
RecyclerView recycle;
ArrayList<LoadHomeBooks> list;
HomeBookAdapter adapter;
EditText search;
private static final String URL = "https://www.example.com";
public Home() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
recycle = view.findViewById(R.id.recycle);
refresh = view.findViewById(R.id.refresh);
search = view.findViewById(R.id.search);
list = new ArrayList<>();
recycle.setHasFixedSize(true);
recycle.setLayoutManager(new LinearLayoutManager(getActivity()));
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(22, TimeUnit.SECONDS)
.readTimeout(22, TimeUnit.SECONDS)
.writeTimeout(22, TimeUnit.SECONDS)
.build();
RequestBody formBody = new FormBody.Builder().add("city", myValue).build();
Request request = new Request.Builder().url(URL).post(formBody).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONArray jsonArray = new JSONArray(response.body().string());
for (int i = jsonArray.length() - 1; i > -1; i--) {
JSONObject object = jsonArray.getJSONObject(i);
String str1 = object.getString("Book_name");
LoadHomeBooks model = new LoadHomeBooks(str1);
list.add(model);
}
adapter = new HomeBookAdapter(list, getActivity());
recycle.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public void onFailure(Call call, final IOException e) {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
TastyToast.makeText(getActivity(), e.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
}
});
}
}
});
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
ArrayList<LoadHomeBooks> filterBooks = new ArrayList<>();
for(LoadHomeBooks books: list){
String name = books.getbName().toLowerCase();
if(name.contains(s)){
filterBooks.add(books);
}
adapter.setFilter(filterBooks);
}
}
});
return view;
}
}
HomeBookAdapter.java
public class HomeBookAdapter extends RecyclerView.Adapter<HomeBookAdapter.ViewHolder> {
ArrayList<LoadHomeBooks> list;
Context context;
public HomeBookAdapter(ArrayList<LoadHomeBooks> list,Context context){
this.list = list;
this.context = context;
}
#NonNull
#Override
public HomeBookAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.home_book_layout,viewGroup,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull HomeBookAdapter.ViewHolder viewHolder, int i) {
LoadHomeBooks model = list.get(i);
viewHolder.homeBookName.setText(model.getbName());
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView homeBookName;
public ViewHolder(#NonNull View itemView) {
super(itemView);
homeBookName = itemView.findViewById(R.id.homeBookName);
}
}
public void setFilter(ArrayList<LoadHomeBooks> filterBooks){
list = new ArrayList<>();
list.addAll(filterBooks);
notifyDataSetChanged();
}
}
LoadHomeBooks.java
public class LoadHomeBooks {
String bName;
public LoadHomeBooks(){
}
public LoadHomeBooks(String bName){
this.bName = bName;
}
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
}
Someone please let me know what I am doing wrong. Any help would be appreciated.
THANKS
Move this code outside the for Loop
adapter.setFilter(filterBooks);
Because adapter is calling set Filter after each iteration.
Also I would request you to move network request to Activity instead of Fragment using interface.
for(LoadHomeBooks books: list){
String name = books.getbName().toLowerCase();
if(name.contains(s)){
filterBooks.add(books);
}
adapter.setFilter(filterBooks); //Place this line outside forloop
}

RecyclerView doesn't inflate, rather updates the same view?

I have an activity to implement a to-do list, containing a recyclerview with each item being a checkbox and textview, and each task is added from an edittext.
It stores data using Realm.io. The behaviour that I keep getting is that the single element in the recyclerview merely get updated, and not inflated! Please help.
TasksActivity -
public class TasksActivity extends AppCompatActivity implements View.OnClickListener{
TextView courseTitle;
RecyclerView TaskList;
EditText addTask;
Button addButton;
String transName; //Transferred Course name from MainActivity
TaskAdapter TA;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks);
courseTitle = findViewById(R.id.CourseName);
TaskList = findViewById(R.id.TaskListRV);
TaskList.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
addTask = findViewById(R.id.InputTask);
addButton = findViewById(R.id.AddTaskButton);
//Course name is the obtained from the previous acivity.
transName =getIntent().getExtras().getString("CourseName");
courseTitle.setText(transName);
TA = new TaskAdapter(transName);
TaskList.setAdapter(TA);
addButton.setOnClickListener(this);
}
#Override
public void onClick(View view) {
String task = addTask.getText().toString();
// Checking if the text is empty.
boolean flag = false;
for(int i = 0;i<task.length();i++)
{
if(task.charAt(i)!=' ')
flag = true;
}
if(!flag || task.equals(""))
{
Toast emptyWarning = Toast.makeText(getApplicationContext(),"Task cannot be Empty!",Toast.LENGTH_SHORT);
emptyWarning.show();
}
else
{
addTask.setText("");
TA.addNewTask(task);
}
}
}
TasksAdapter -
public class TaskAdapter extends RecyclerView.Adapter<TaskViewHolder> implements RealmChangeListener<RealmResults<TaskModel>>
{
private ArrayList<TaskModel> TaskList;
private String course;
private final Realm realm;
public TaskAdapter(String course)
{
this.course = course;
this.TaskList = new ArrayList<>();
realm = Realm.getDefaultInstance();
loadTaskData();
}
void loadTaskData()
{
RealmResults<TaskModel> taskModelRealmResults = realm.where(TaskModel.class).equalTo("courseName",course).findAll();
taskModelRealmResults.addChangeListener(this);
for(TaskModel iTM : taskModelRealmResults)
{
TaskList.add(realm.copyFromRealm(iTM));
}
notifyDataSetChanged();
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view= layoutInflater.inflate(R.layout.item_task,parent,false);
TaskViewHolder Tvh = new TaskViewHolder(view);
return Tvh;
}
#Override
public void onBindViewHolder(TaskViewHolder holder, int position) {
holder.populateTask(TaskList.get(position));
}
#Override
public int getItemCount() {
return TaskList.size();
}
public void addNewTask(String task)
{
TaskModel newTaskObj = new TaskModel(task,course,false);
TaskList.add(newTaskObj);
notifyDataSetChanged();
realm.beginTransaction();
realm.insertOrUpdate(newTaskObj);
realm.commitTransaction();
}
#Override
public void onChange(RealmResults<TaskModel> taskModels) {
taskModels = realm.where(TaskModel.class).equalTo("courseName",course).findAll();
this.TaskList = new ArrayList<>();
for(TaskModel iTM : taskModels)
{
this.TaskList.add(realm.copyFromRealm(iTM));
}
notifyDataSetChanged();
}
}
TaskViewHolder and TaskModel - (in case you might need them)
public class TaskModel extends RealmObject {
String task;
#PrimaryKey
String courseName;
boolean isDone;
public TaskModel() {
task = "";
courseName = "";
isDone = false;
}
public TaskModel(String task, String courseName, boolean isDone) {
this.task = task;
this.courseName = courseName;
this.isDone = isDone;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
public boolean isDone() {
return isDone;
}
public void setDone(boolean done) {
isDone = done;
}
}
public class TaskViewHolder extends RecyclerView.ViewHolder {
CheckBox isdone;
TextView Taskname;
public TaskViewHolder(View itemView) {
super(itemView);
isdone = itemView.findViewById(R.id.TaskCheckBox);
Taskname = itemView.findViewById(R.id.TaskName);
}
void populateTask(final TaskModel T)
{
Taskname.setText(T.getTask());
isdone.setChecked(T.isDone());
isdone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
T.setDone(isdone.isChecked());
}
});
}
}
I advise you to use Realm Android dapter, this adapter is taking care of updating your app UI. Don't need to implement OnChangeListener, your list will be automatically updated after insertion, deletion or edition
Use findAllAsync in order to not block the UI thread
OrderedRealmCollection<TaskModel> taskModels = realm.where(TaskModel.class).equalTo("courseName", course).findAllAsync();
public RealmAdapter(OrderedRealmCollection<TaskModel> data) {
super(data, true);
}
EDIT:
Also always do the process using Async method when it's possible. You can replace your addNewTask method by:
public void addNewTask(String task) {
final TaskModel newTaskObj = new TaskModel(task, course, false);
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(newTaskObj);
}
});
}
Yous should have something like this:
TasksActivity
public class TasksActivity extends AppCompatActivity implements View.OnClickListener {
private EditText addTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks);
String transName = getIntent().getExtras().getString("CourseName");
TextView courseTitle = findViewById(R.id.CourseName);
courseTitle.setText(transName);
addTask = findViewById(R.id.InputTask);
findViewById(R.id.AddTaskButton).setOnClickListener(this);
OrderedRealmCollection<TaskModel> taskModels = Realm.getDefaultInstance().where(TaskModel.class).equalTo("courseName", transName).findAllAsync()
TaskAdapter adapter = new TaskAdapter(this, taskModels);
RecyclerView taskList = findViewById(R.id.TaskListRV);
taskList.setLayoutManager(new LinearLayoutManager(this));
taskList.setAdapter(adapter);
}
#Override
public void onClick(View view) {
String task = addTask.getText().toString().trim();
if (task.trim().isEmpty()) {
Toast emptyWarning = Toast.makeText(getApplicationContext(),"Task cannot be Empty!",Toast.LENGTH_SHORT);
emptyWarning.show();
return;
}
addTask.setText("");
addNewTask(task);
}
private void addNewTask(String task) {
final TaskModel newTaskObj = new TaskModel(task, course, false);
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(newTaskObj);
}
});
}
}
And TaskAdapter:
public class TaskAdapter extends RealmRecyclerViewAdapter<TaskModel, TaskViewHolder> {
private LayoutInflater layoutInflater
public TaskAdapter(Context context, OrderedRealmCollection<TaskModel> taskModels) {
super(taskModels, true);
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new TaskViewHolder(layoutInflater.inflate(R.layout.item_task , parent, false));
}
#Override
public void onBindViewHolder(TaskViewHolder holder, int position) {
holder.populateTask(getItem(position));
}
}
OP here. I ended up using the standard ReacyclerView.Adapter.
The problem was with the usage of Realm's insertOrUpdate method, when the #PrimaryKey was courseName which thus caused it to indeed update the same object and not create a new one!
insert() should have been used.
Here is the insert task method -
public void addNewTask(String task)
{
boolean flag = false;
for(int i = 0;i<TaskList.size();i++)
{
if(task.equals(TaskList.get(i).getTask()))
{
Toast.makeText(context,"Task already exists!",Toast.LENGTH_SHORT).show();
flag = true;
break;
}
}
if(!flag)
{
TaskModel newTaskObj = new TaskModel();
newTaskObj.setTask(task);
newTaskObj.setDone(false);
newTaskObj.setCourseName(course);
TaskList.add(newTaskObj);
notifyDataSetChanged();
realm.beginTransaction();
realm.insert(newTaskObj);
realm.commitTransaction();
} }
The entire project can be found here, do check it out -
https://github.com/Hariram-R/ToDoList-App

toogle listener associated with checkbox with adapter

Im building a simple aplication with a recycleView/CardLayout, i followeed this tutorial.
I see many questions answered for the card click, but what i need is to handle listeners with diferent actions when the user clicks the title or the user clicks on the image in each card.
My problem is, when the user clicks a radiobutton i need to get the radio on the listener so i can handle check and uncheck because i need to do pass that to a builder
This is what i have at the moment:
public class SimiliarPlantsAdapter extends RecyclerView.Adapter<SimiliarPlantsAdapter.PlantViewHolder>{
ArrayList<Plant> plants = new ArrayList<Plant>();
Context context;
public static class PlantViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView plantName;
CheckBox plantCheck;
ImageView plantPhoto;
PlantViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
plantName = (TextView)itemView.findViewById(R.id.plantName);
plantCheck = (CheckBox)itemView.findViewById(R.id.plantCheck);
plantPhoto = (ImageView)itemView.findViewById(R.id.plantPhoto);
}
}
#Override
public PlantViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.similiar_photo_row, viewGroup, false);
PlantViewHolder pvh = new PlantViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PlantViewHolder holder, int position) {
holder.plantName.setText(plants.get(position).getSpecie());
holder.plantCheck.setText("Are you sure this is the plant?");
Log.d("foto",String.valueOf(holder.plantName));
String urlFoto = "http://10.0.2.2:3000/images/" + holder.plantName.getText().toString() + "/Thumbnail.jpg";
Picasso.with(context)
.load(urlFoto)
.resize(250, 250)
.into(holder.plantPhoto);
}
#Override
public int getItemCount() {
return plants.size();
}
public SimiliarPlantsAdapter(ArrayList<Plant> plants,Context context) {
this.plants = plants;
this.context = context;
}
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
MY Activity
public class SimiliarPhotos extends AppCompatActivity implements IResult,SimiliarPlantsAdapter.OnItemClickListener {
RecyclerView rv;
LinearLayoutManager llm;
ArrayList<Plant> plants = new ArrayList<Plant>();
SimiliarPlantsAdapter adapter;
CheckBox checkBox;
VolleyService mVolleyService;
IResult mResultCallback = null;
final String GETREQUEST = "GETCALL";
//login url connection
final String URL = "http://10.0.2.2:3000/plants";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_similiar_photos);
rv = (RecyclerView)findViewById(R.id.rv);
llm = new LinearLayoutManager(this);
llm.setAutoMeasureEnabled(true);
rv.setLayoutManager(llm);
initializeAdapter();
initVolleyCallback();
mVolleyService = new VolleyService(mResultCallback,this);
mVolleyService.getDataVolley(GETREQUEST,URL);
}
#Override
public void notifySuccess(String requestType, JSONObject response) {
Log.d("resposta",response.toString());
}
#Override
public void notifySuccess(String requestType, JSONArray response) {
Log.d("resposta",response.toString());
}
#Override
public void notifyError(String requestType, VolleyError error) {
Log.d("resposta",error.toString());
}
void initVolleyCallback(){
mResultCallback = new IResult() {
#Override
public void notifySuccess(String requestType, JSONObject response) {
}
#Override
public void notifySuccess(String requestType, JSONArray response) {
Plant plant;
Log.d("ENTERED","ENTEREDHERE1");
// iterate over the JSONArray response
for (int i=0; i < response.length(); i++) {
try {
JSONObject object = response.getJSONObject(i); // get the individual object from JSONArray
int id = Integer.parseInt(object.getString("id")); // get the unique identifier from the object
String specie = object.getString("specie"); // get the name of the specie from the object
String description = object.getString("description"); // get the description of the object
plant = new Plant(id,specie,description); // construct the object
Log.d("plant",String.valueOf(plant));
plants.add(plant); // add the object to the arraylist so it can be used on the cardLayout
} catch (JSONException e) {
Log.d("ENTERED",e.toString());
e.printStackTrace();
}
}
adapter.notifyDataSetChanged();
}
#Override
public void notifyError(String requestType, VolleyError error) {
Log.d("resposta",error.toString());
}
};
}
public void initializeAdapter(){
Log.d("plants",String.valueOf(plants.size()));
adapter = new SimiliarPlantsAdapter(plants,SimiliarPhotos.this,SimiliarPhotos.this);
rv.setAdapter(adapter);
}
#Override
public void onTitleClicked(int position, int id, View clickedview) {
}
#Override
public void onImageClicked(int position, View clickedview) {
}
#Override
public void onCheckClicked(int position, String specie, View clickedview) {
adapter.getItemId(position);
CreateDialog(specie);
}
public void CreateDialog(String specie){
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(SimiliarPhotos.this, android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(SimiliarPhotos.this);
}
builder.setTitle("Esta é a sua escolha?")
.setMessage("Confirma " + specie + " como a planta que fotografou?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//TODO associa nome da planta a fotografia na base de dados
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
The volley init is the request, not so important for the question, since i get the data correctly
You need to implement CompoundButton.OnCheckedChangeListener for CheckBox.
Your_CHECK_BOX.setOnCheckedChangeListener(checkedChangeListener);
CompoundButton.OnCheckedChangeListener checkedChangeListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(compoundButton == YOUR_CHECK_BOX) {
if(isChecked) {
// when check box is checked, call your action listener just like you did for title click/image click etc
} else {
// when check box is unchecked, call your action listener just like you did for title click/image click etc
}
}

Categories