Why TextWatcher is not working in custom Edittext in android? - android-edittext

I am working on custom edittext but i am little stuck in one thing, i found TextWatcher is not working in custom edittext.
public class InputValidation extends EditText {
public InputValidation(Context context) {
super(context);
}
public InputValidation(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InputValidation(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void addTextChangedListener(android.text.TextWatcher watcher) {
super.addTextChangedListener(new TextWatcherDelegator());
}
public class TextWatcherDelegator implements android.text.TextWatcher {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
android.util.Log.d("TextWatcher", " beforeTextChanged :: " + charSequence.toString());
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(android.text.Editable editable) {
android.util.Log.d("TextWatcher", " afterTextChanged :: " + editable.toString());
}
}
}
XML layout
<com.example.inputvalidation.InputValidation
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:hint="Fullname"
android:singleLine="true"
android:textSize="20sp"/>
Above this code it's not at all calling TextWatcher states, please kindly go through my code and suggest me some solution.

Remove this, it's useless:
#Override
public void addTextChangedListener(android.text.TextWatcher watcher) {
super.addTextChangedListener(new TextWatcherDelegator());
}
Then, add/remove the TextWatcher properly, for example in onAttachedToWindow/onDetachedFromWindow methods:
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
addTextChangedListener(textWatcher);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeTextChangedListener(textWatcher);
}
Also, textWatcher should be an object, so it can be instanced from the TextWatcherDelegator class:
TextWatcherDelegator textWatcher = new TextWatcherDelegator();
Or directly from TextWatcher (which is better, if there's no other usages for TextWatcherDelegator):
public TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
android.util.Log.d("TextWatcher", " beforeTextChanged :: " + charSequence.toString());
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(android.text.Editable editable) {
android.util.Log.d("TextWatcher", " afterTextChanged :: " + editable.toString());
}
}

Related

viewholder onclickListener null object reference

Attempt to invoke interface method 'void com.example.imovie.adapter.MovieItemClickListener.onMovieClick(com.example.imovie.models.Movie, android.widget.ImageView)' on a null object reference
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MyViewHolder> {
Context context ;
List<Movie> mData;
MovieItemClickListener movieItemClickListener;
public MovieAdapter(Context context, List<Movie> mData, MovieItemClickListener listener) {
this.context = context;
this.mData = mData;
movieItemClickListener = listener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.item_movie,viewGroup,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.TvTitle.setText(mData.get(i).getTitle());
myViewHolder.ImgMovie.setImageResource(mData.get(i).getThumbnail());
}
#Override
public int getItemCount() {
return mData.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView TvTitle;
private ImageView ImgMovie;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
TvTitle = itemView.findViewById(R.id.item_movie_title);
ImgMovie = itemView.findViewById(R.id.item_movie_img);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
movieItemClickListener.onMovieClick(mData.get(getAdapterPosition()),ImgMovie);//i have a null object reference
}
});
}
}
}
public class HomeFragment extends Fragment implements MovieItemClickListener {
private HomeViewModel homeViewModel;
private List<Slide> listSlides;
private ViewPager slidePager;
private TabLayout indicator;
private RecyclerView moviesRV;
private RecyclerView moviesRV2;
private MovieItemClickListener movieItemClickListener;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
slidePager = root.findViewById(R.id.slider_pager);
indicator = root.findViewById(R.id.indicator);
moviesRV = root.findViewById(R.id.rsViewMovies);
moviesRV2 = root.findViewById(R.id.rsViewMovies2);
iniSlider();
final SliderPagerAdapter sliderPagerAdapteradapter = new SliderPagerAdapter(getContext(), listSlides);
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new SliderTimer(), 4000, 6000);
homeViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
slidePager.setAdapter(sliderPagerAdapteradapter);
indicator.setupWithViewPager(slidePager, true);
moviesRV.setAdapter(movieAdapter);
moviesRV.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
moviesRV2.setAdapter(movieAdapter);
moviesRV2.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
}
});
return root;
}
#Override
public void onMovieClick(Movie movie, ImageView imageView) {
Intent intent = new Intent(getContext(), MovieDetailActivity.class);
intent.putExtra("title", movie.getTitle());
intent.putExtra("imgURL", movie.getThumbnail());
intent.putExtra("imgCover", movie.getCoverPhoto());
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
imageView, "sharedName");
startActivity(intent, options.toBundle());
Toast.makeText(getContext(), "item clicked : " + movie.getTitle(), Toast.LENGTH_LONG).show();
}
class SliderTimer extends TimerTask {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (slidePager.getCurrentItem() < listSlides.size() - 1) {
slidePager.setCurrentItem(slidePager.getCurrentItem() + 1);
} else {
slidePager.setCurrentItem(0);
}
}
});
}
}
}
private void iniSlider() {
listSlides = new ArrayList<>();
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
}
}
If I'm not wrong, HomeFragment.movieItemClickListener is never initialized.
You may want to make the following changes in HomeFragment:
1. Delete the line
private MovieItemClickListener movieItemClickListener;
2. In this line
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
change movieItemClickListener to this, because HomeFragment implements MovieItemClickListener.
That should fix the NullPointerException.

I'm using **Libgdx**, input events don't work when using **Multi-OS Engine**

It works fine in Android and Desktop. But when running on iOS, it doesn't respond any input event.
I'm using gdxVersion 1.9.5, multi-os engine 1.2.3
I wrote a test class extends input adapter and override touchDown and touchUp method. But it doesn't respond any of the input events which work fine in Android.
public class TestScreen extends ScreenAdapter implements InputProcessor {
private CardGame game;
private OrthographicCamera guiCam;
public TestScreen(CardGame game){
this.game = game;
guiCam = new OrthographicCamera(Consts.WORLD_WIDTH, Consts.WORLD_HEIGHT);
Gdx.input.setInputProcessor(this);
}
public void draw () {
GL20 gl = Gdx.gl;
gl.glClearColor(1, 0, 0, 1);
gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
guiCam.update();
}
public void render (float delta) {
draw();
}
#Override
public boolean keyDown(int keycode) {
System.out.println("key down");
return true;
}
#Override
public boolean keyUp(int keycode) {
System.out.println("key up");
return true;
}
#Override
public boolean keyTyped(char character) {
System.out.println("key typed");
return true;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
System.out.println("touch down");
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
System.out.println("touch up");
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
System.out.println("touch dragged");
return true;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
System.out.println("mouse moved");
return true;
}
#Override
public boolean scrolled(int amount) {
System.out.println("scrolled");
return true;
}
}

populate images with firebase recycler adapter through databinding

I am populating a firebase data with firebase recycler adapter through databinding and want to populate images with the data either from Picasso or Glide, but unable to do. So can any one help me what to write and where to write the code of either Picasso or Glide.
public class ShopByCategoryFragment extends Fragment {
FirebaseRecyclerAdapter adapter;
Firebase mFirebaseRef = new Firebase("https://abc.firebaseio.com/").child("subCategories");
public ShopByCategoryFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view, container, false);
final RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
adapter = new FirebaseRecyclerAdapter<SubCategories, ViewHolder>(SubCategories.class, R.layout.fragment_shop_by_category,
ViewHolder.class, mFirebaseRef) {
#Override
protected void populateViewHolder(ViewHolder viewHolder, SubCategories subCategories, int i) {
FragmentShopByCategoryBinding binding = viewHolder.getBinding();
binding.setSubCategories(subCategories);
}
};
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
return rootView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public FragmentShopByCategoryBinding binding;
public ViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
public FragmentShopByCategoryBinding getBinding() {
return binding;
}
}
#Override
public void onDestroy() {
super.onDestroy();
adapter.cleanup();
}
}
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="SubCategories"
type="com.abc.www.shopping.model.SubCategories"/>
</data>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:id="#+id/sub_category_image"
android:scaleType="centerCrop"
android:src="#{SubCategories.image}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:text="#{SubCategories.title}"
android:id="#+id/sub_category_title"
android:padding="16dp"
android:textColor="#color/colorSubCategoryTitle"
android:layout_gravity="center"
android:textAppearance="#android:style/TextAppearance.Material.Title"
tools:targetApi="lollipop" />
</FrameLayout>
</android.support.v7.widget.CardView>
public class SubCategories extends BaseObservable {
private String title;
private String image;
public SubCategories() {
// empty constructor
}
public SubCategories(String title, String image) {
this.title = title;
this.image = image;
}
public String getTitle() {
return title;
}
public String getImage() {
return image;
}
}
I have made something similar to what you need. I'll share my code and do a little explanation.
I have a class that returns the FirebaseRecyclerAdapter like this:
public RecyclerView.Adapter postAdapter(String userKey, final Context context, MyClickListener clickListener) {
Query userPostRef = postRef.child(userKey);
myClickListener = clickListener;
return new FirebaseRecyclerAdapter<PostModel, DataObjectHolder>(PostModel.class, R.layout.stream_layout, DataObjectHolder.class, userPostRef) {
#Override
public void populateViewHolder(final DataObjectHolder dataviewHolder, final PostModel postModel, int position) {
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
mStorageRef.child("uploaded_captures/" + postModel.getImageFilename() + ".jpg").getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
dataviewHolder.setImage(uri.toString(), context);
dataviewHolder.setComment(postModel.getPostComment());
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("FirebaseRecyclerAdapter", exception.getMessage());
}
});
}
};
}
and a ViewHolder that loads the image into the ImageView used by the layout:
private static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View mView;
public DataObjectHolder(View itemView) {
super(itemView);
mView = itemView;
}
void setImage(final String imageURL, final Context context) {
final ImageView postImage = (ImageView) mView.findViewById(R.id.imageView);
if (BuildConfig.DEBUG) {
Picasso.with(context).setIndicatorsEnabled(true);
}
Picasso.with(context)
.load(imageURL)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(context)
.load(imageURL)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage);
}
});
}
void setComment(String text) {
TextView comment = (TextView) mView.findViewById(R.id.comment);
comment.setText(text);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
On Picasso I'm using the NerworkPolicy.OFFLINE to check if the image is on the disk cache before trying to get it from the network. It's not perfect and I'm still having some issues with the delay of the images once the ViewHolder it's been recycled but I think it's a start for you to go on.
In my ViewHolder I do this by:
Glide.with(context)
.load(chat.getImageUrl())
.into(imageView);
I haven't tried using data binding for this yet, but the code is simple enough.

Checkbox enable EditText in RecyclerView issue

I am working for quiz app project. I've got a RecyclerView, each of them contains TextView, two Checkbox and EditText. What I want is when i checked the second Checkbox it will enable the EditText. I have already make this work. but the problem is if I Checked the Checkbox and Type something in the EditText on the first row, when I scroll down some of the others are mirroring the EditText state even I am not Checked the Checkbox to enable EditText of that row.
here is my adapter code:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.chbIllegal.setChecked(students.get(position).isSelected());
holder.chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
final Student contact = (Student) cb.getTag();
contact.setSelected(cb.isChecked());
students.get(position).setSelected(cb.isChecked());
// this will enable editText if checkbox is checked
if (cb.isChecked()) {
holder.editText.setEnabled(true);
holder.editText.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) {
String Illegal = holder.editText.getText().toString();
contact.setAgaints_rule(Illegal);
Log.d("GExam", currentStudent.student + " " + Illegal);
}
});
holder.chbIllegal.setOnClickListener(null);
holder.chbIllegal.setTag(students.get(position));
} else {
holder.editText.setEnabled(false);
}
}
});
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
// chbIllegal will handle the editText
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
editText.setEnabled(false);
}
}
public List<Student> getStudentList() {
return students;
}
}
How can I only enable EditText of the row that checkbox is checked?
Finally I've been able to solve my problem by my teacher helped. what I have changed is I move the listener from onBindViewHolder to my ViewHolder class like this:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.editText.setText(currentStudent.getAgaints_rule());
if (currentStudent.isSelected()) {
holder.editText.setEnabled(true);
}else{
holder.editText.setEnabled(false);
}
holder.chbIllegal.setChecked(students.get(position).isSelected());
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Student s = (Student) v.getTag();
Log.e("GExam", String.valueOf(cb.isChecked()));
s.setSelected(cb.isChecked());
StudentViewHolder.this.editText.setEnabled(cb.isChecked());
}
});
editText.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) {
Student student = (Student) StudentViewHolder.this.editText.getTag();
student.setAgaints_rule(s.toString());
}
});
}
}
public List<Student> getStudentList() {
return students;
}
}

How to get parent of a custom component?

I have a custom container component, that I want to use like this:
<p:a>A
<p:a>B</p:a>
</p:a>
That should generate this markup:
<div>A
<div>B</div>
</div>
Code for the component is below.
public class TagA extends TagHandler {
Logger logger = Logger.getLogger(getClass().getName());
public TagA(TagConfig config) {
super(config);
}
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException {
UIComponentBase c = new UIComponentBase() {
public void encodeBegin(FacesContext ctx) throws IOException {
//getParent() always returns UIViewRot
logger.info("Parent is: " + getParent().getClass().getName());
ResponseWriter w = ctx.getResponseWriter();
w.write("<div>");
super.encodeBegin(ctx);
}
public void encodeEnd(FacesContext ctx) throws IOException {
ResponseWriter w = ctx.getResponseWriter();
w.write("</div>");
super.encodeEnd(ctx);
}
// abstract method in base, must override
public String getFamily() {
return "com.mobiarch.nf";
}
};
parent.getChildren().add(c);
nextHandler.apply(ctx, parent);
}
}
Unfortunately, this is rendering the following markup:
<div></div>A
<div></div>B
For others in a similar situation, just develop the component and not the tag.
#FacesComponent("my.ComponentA")
public class ComponentA extends UIComponentBase {
Logger logger = Logger.getLogger(getClass().getName());
public String getFamily() {
return "my.custom.component";
}
public void encodeBegin(FacesContext ctx) throws IOException {
super.encodeBegin(ctx);
logger.info("Component parent is: " + getParent().getClass().getName());
ResponseWriter w = ctx.getResponseWriter();
w.write("<div>");
}
public void encodeEnd(FacesContext ctx) throws IOException {
super.encodeEnd(ctx);
ResponseWriter w = ctx.getResponseWriter();
w.write("</div>");
}
}
Register it in your ??.taglib.xml
<tag>
<tag-name>a</tag-name>
<component>
<component-type>my.ComponentA</component-type>
</component>
</tag>

Resources