Android EditText not visible and does not show keyboard - android

Using the following layouts and views below, I cannot get the EditText et_messageText box to show up in my display properly. If I run this in the emulator, I am able to click in the area and get a "null" selection cursor, so I know the EditText is there, but the keyboard never shows, and I am not able to get input to work. What am I doing wrong?
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.project.model.MyViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.project.MainActivity">
<com.example.project.view.ChannelHeaderView
android:id="#+id/channelHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" />
<com.example.project.view.MessageInputView
android:id="#+id/message_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</layout>
message_input.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.project.model.MyViewMOdel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="#+id/iv_send"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="13dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="#drawable/stream_ic_send" />
<EditText
android:id="#+id/et_messageText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="112dp"
android:ems="10"
android:inputType="text"
android:text="#={viewModel.inputText}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/iv_send"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MessageInputView.java
public class MessageInputView extends RelativeLayout {
private MessageInputBinding binding;
private MyViewModel viewModel;
public MessageInputView(Context context) {
super(context);
binding = initBinding(context);
}
public MessageInputView(Context context, AttributeSet attrs) {
super(context, attrs);
binding = initBinding(context);
// Focus Listening
binding.etMessageText.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
binding.etMessageText.setTextIsSelectable(true);
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(v,InputMethodManager.SHOW_FORCED);
}
});
}
private MessageInputBinding initBinding(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
binding = MessageInputBinding.inflate(inflater, this, true);
binding.etMessageText.clearFocus();
return binding;
}
public void setViewModel(MyViewMOdel model, LifecycleOwner lifecycleOwner) {
this.viewModel = model;
binding.setLifecycleOwner(lifecycleOwner);
binding.setViewModel(viewModel);
}
}
and finally in the onCreate() of
MainActivity.java
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setLifecycleOwner(this);
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.setPreferences(this);
binding.setViewModel(viewModel);
binding.channelHeader.setViewModel(viewModel, this);
binding.messageInput.setViewModel(viewModel, this);

Why are you extending your MessageInputView class with RelativeLayout?
I guess that your MessageInputView class is a Fragment so extend it with Fragment and use the default LayoutInflater inflater and ViewGroup container.
Hence your:
private MessageInputBinding initBinding(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
binding = MessageInputBinding.inflate(inflater, this, true);
binding.etMessageText.clearFocus();
return binding;
}
Should be like this:
private MessageInputBinding initBinding(LayoutInflater inflater, ViewGroup container) {
binding = DataBindingUtil.inflate(inflater, R.layout.message_input, container, false);
binding.etMessageText.clearFocus();
return binding;
}

Related

Drop down popup not display while search on autocompletetextview in android

I have stuck with this issue more then 3 days. I have used one RecyclerView and on recyclerview's each item have on AutoCompleteTextView. When try to search on autocompletetextview drop down not display. Please do some help that how or where I need to update my code to use atutocomplettextview in every recyclerview items.
I have tried below are the cases:
To show popup manually autoCompleteTextView.showDropDown()
notify adapter when user is typing in autocompletetextview
Every time reset the new adapter once use type on autocompletetextview
I have tried all the option's of android:windowSoftInputMode="" in AndroidMenifest
Checked more then 20+ questions on StackOver
I have tried to set ArrayAdapter from onBindViewHolder() method also
Below are the my code:
This is activity xml file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com..job..i.viewModel.job.JobViewModel" />
<import type="android.view.View" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/screenBG"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvSupervisor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:itemCount="1"
tools:listitem="#layout/job_filter_adapter" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
This is adapter class
public class JobFilterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public final String tag = JobFilterAdapter.class.getSimpleName();
private final Activity _activity;
private final LayoutInflater inflater;
private final List<StaffInfo> _staffList;
private final List<String> jobList;
public JobFilterAdapter(Activity activity, List<StaffInfo> staffList,
List<String> list) {
jobStaffAdapter = this;
_activity = activity;
inflater = _activity.getLayoutInflater();
_staffList = staffList;
jobList = list;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new AdapterHolder(DataBindingUtil.inflate(inflater, R.layout.row_job, parent, false),
new JObWatcher());
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, #SuppressLint("RecyclerView") int position) {
AdapterHolder adapterHolder = (AdapterHolder) holder;
StaffInfo model = _staffList.get(holder.getAdapterPosition());
adapterHolder.binding.autoCompleteTxtJob.setText(model.getStaffNo(), false);
adapterHolder.binding.txtStaffName.setText(model.getStaffName());
adapterHolder.jobWatcher.updateState(position, adapterHolder);
}
#Override
public int getItemCount() {
return _staffList.size();
}
class AdapterHolder extends RecyclerView.ViewHolder {
private final RowJobBinding binding;
JObWatcher jobWatcher;
ArrayAdapter jobArrayAdapter;
public AdapterHolder(#NonNull RowJobBinding _binding, JObWatcher _jobWatcher) {
super(_binding.getRoot());
binding = _binding;
jobWatcher = _jobWatcher;
jobArrayAdapter = new ArrayAdapter(_activity, R.layout.row_job_item,jobList);
binding.autoCompleteTxtJob.setThreshold(1);
}
}
public class JObWatcher {
int position;
AdapterHolder holder;
private void updateState(int pos, AdapterHolder viewHolder) {
position = pos;
holder = viewHolder;
manageAutoText();
}
private void manageAutoText() {
holder.binding.autoCompleteTxtJob.setOnFocusChangeListener((view, b) -> {
if (b) {
holder.binding.autoCompleteTxtJob.setAdapter(holder.jobArrayAdapter);
} else {
holder.binding.autoCompleteTxtJob.setAdapter(null);
}
});
}
}
}
This is adapter's item xml file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_5sdp"
android:padding="#dimen/_5sdp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="#dimen/_25sdp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
style="#style/txtJobDetailRowLeft"
android:text="#string/lbl_job" />
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
android:id="#+id/autoCompleteTxtJob"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="6"
android:background="#drawable/bg_et_first"
android:gravity="center_vertical"
android:inputType="text"
android:paddingLeft="#dimen/_5sdp"
android:singleLine="true"
android:textColor="#color/black"
android:textSize="#dimen/_9sdp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="#dimen/_25sdp"
android:layout_marginTop="#dimen/_5sdp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
style="#style/txtJobDetailRowLeft"
android:text="#string/lbl_staff_name" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/txtStaffName"
style="#style/txtJobDetailRowRight" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Handle button event of ListView of Fragment class?

I have used two Fragment in my code. I have to display a custom ListView in each fragment. But I would like to handle Button's onClickListener event which is in this ListView.
I can't find online how to use these Button (ImageButton, actually) components in Fragment class.
Here is my code:
My fragment class:
public class tabtodo extends Fragment implements View.OnClickListener {
public tabtodo() {}
private View view, view2;
private ListView lstTask;
private ImageButton btndelete;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tabtodo, container, false);
lstTask = (ListView) view.findViewById(R.id.listView);
AlUpdater alUpdater = new AlUpdater(getContext());
lstTask.setAdapter(alUpdater.getAdapterTodo());
view2 = inflater.inflate(R.layout.row, container, false);
btndelete = (ImageButton) view2.findViewById(R.id.btntest);
btnTest.setOnClickListener(this);
return mView;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btntest:
Log.i("prova", "prova ");
break;
default:
Log.i("prova", "def");
break;
}
}
alUpdater.getAdapterTodo() is:
public ArrayAdapter < String > getAdapterTodo() {
ArrayList < String > taskList = (dG).getListTodo("todo");
if (adptodo == null) {
adptodo = new ArrayAdapter < > (context, R.layout.row, R.id.task_title, taskList);
adptodo.notifyDataSetChanged();
} else {
adptodo.clear();
adptodo.addAll(taskList);
adptodo.notifyDataSetChanged();
}
return adptodo;
}
as you can see, I am using a custom layout for the arrayadapter.
R.layout.fragment_tabtodo: is a fragment with just a listview:
<?xml version="1.0" encoding="utf-8"?>`
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".tabtodo"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:background="#color/white">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/white"
android:dividerHeight="0dp"
android:footerDividersEnabled="true"
android:headerDividersEnabled="true">
</ListView>
</FrameLayout>
and finally, the XML of the row of the adapter (**R.layout.row**):
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingVertical="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/themeselector">
<TextView
android:id="#+id/task_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginEnd="10dp"
android:text="TASK"
android:textColor="#color/white"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btnGoToDone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints" />
<ImageButton
android:id="#+id/btnGoToDone"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:backgroundTint="#android:color/transparent"
android:onClick="switchTodoDone"
android:src="#drawable/ic_done_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btndelete"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="#+id/btndelete"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:backgroundTint="#android:color/transparent"
android:src="#drawable/ic_delete_icon"
android:onClick="deleteTask"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
you need to create a custom adapter for you ListView. and handle the button click there.
check this tutorial here
I would recommend that you use RecyclerView instead of ListView since it enforces the ViewHolder pattern which improves the performance.

onclick using databinding in fragment

I am trying to implement data binding in a Fragment but it's not working, the same code is working in Activity.
Fragment class
final FragmentHomeBinding fragmentHomeBinding = DataBindingUtil.inflate(
inflater, R.layout.fragment_home, container, false);
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
fragmentHomeBinding.setVariable(BR.homeViewModel, homeViewModel);
HomeEventHandler homeEventHandler = new HomeEventHandler(getActivity());
fragmentHomeBinding.setHandler(homeEventHandler);
EventHandlerClass
HomeEventHandler(Context mContext) {
this.mContext = mContext;
}
public void onButtonClick(View view) {
Log.e("DB", "onButtonClick: ");
switch (view.getId()){
case R.id.frag_home_ll_stock:
Toast.makeText(mContext, "clicked", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(mContext, StockCheckActivity.class);
mContext.startActivity(intent);
}
}
and finally the xml file
<data>
<import type="android.view.View" />
<variable
name="fragment"
type="com.poc.ui.home.HomeFragment"/>
<variable
name="handler"
type="com.poc.ui.home.HomeEventHandler"/>
</data>
<LinearLayout
android:onClick="#{view->handler.onButtonClick(view)}"
android:id="#+id/frag_home_ll_stock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#color/grey_25"
android:clickable="true"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<!--
-->
<TextView
android:id="#+id/frag_home_tv_op4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:clickable="false"
android:text="#string/w_stock_check"
android:textColor="#color/black"
android:textSize="18sp" />
<ImageView
android:id="#+id/frag_home_iv_op4"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:clickable="false"
app:srcCompat="#drawable/ic_stock" />
</LinearLayout>
Remove the below line from your Fragment
View root = inflater.inflate(R.layout.fragment_home, container, false);
And If you need the view, you can pass with a parameter like below
android:onClick="#{(view) -> handler.onButtonClick(view)}"
Your LinearLayout should be like the following.
<LinearLayout
android:onClick="#{(view)->handler.onButtonClick(view)}"
android:id="#+id/frag_home_ll_stock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#color/grey_25"
android:clickable="true"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<variable
name="HomeviewModel"
type="com.poc.ui.home.HomeviewModel"/> // exact path
you need to declare the viewmodel variable
android:onClick="#{(v) -> homeViewModel.buttonClicked(v, true)}"
if you are passing the parameter the function also should also contain same parameter
for e.g,
private void buttonClicked(View view, boolean value){
// your code
}
your method should look like this .
Try this one:
<ImageView
android:onClick="#{(view) -> handler.onButtonClick()}"
android:id="#+id/frag_home_iv_op3"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:srcCompat="#drawable/ic_report" />

Empty View on a RecyclerView

In an app I am working on, I am using a Recycler View to show a list of items. I would like the list to display some view (For example, a text view) when the list is empty. I know that with ListViews, one could call setEmptyView, but RecyclerView has no such method.
I have tried setting the visibility of a view to GONE, and making it visible when the RecyclerView dataset is empty, but adding any view to the layout file where the RecyclerView is defined leads to an error:
Attempt to invoke virtual method 'boolean
android.support.v7.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null
object reference
What is the best way to go about what I am doing?
For more info, the RecyclerView is held inside a Fragment, and the layout is inflated in the onCreateView function.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_grocerylist, container, false);
rv = view.findViewById(R.id.grocery_list);
dh = new DatabaseHandler(view.getContext());
dataset = dh.getGroceries();
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
recyclerView.setLayoutManager(new LinearLayoutManager(context));
adapter = new GroceryListRecyclerViewAdapter(dataset,mListener,this);
recyclerView.setAdapter(adapter);
}
ItemTouchHelper.Callback callback = new SimpleTouchHelperCallback(adapter);
ith = new ItemTouchHelper(callback);
ith.attachToRecyclerView(rv);
DividerItemDecoration div = new DividerItemDecoration(rv.getContext(),
DividerItemDecoration.VERTICAL);
rv.addItemDecoration(div);
return view;
}
The XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/grocery_list" android:name="com.github.jlcarveth.grocer.layout.fragment.GroceryListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
app:layoutManager="LinearLayoutManager" tools:context="com.github.jlcarveth.grocer.layout.fragment.GroceryListFragment" tools:listitem="#layout/grocery_item"/>
I updated your code:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:name="com.github.jlcarveth.grocer.layout.fragment.GroceryListFragment"
android:layout_width="match_parent"
tools:context="com.github.jlcarveth.grocer.layout.fragment.GroceryListFragment"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/grocery_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
app:layoutManager="LinearLayoutManager"
tools:listitem="#layout/grocery_item" />
<TextView
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:text="NO DATA AVAILABLE" />
</FrameLayout>
Your Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_grocerylist, container, false);
rv = view.findViewById(R.id.grocery_list);
TextView emptyView = (TextView)view.findViewById(R.id.empty_view);
dh = new DatabaseHandler(view.getContext());
dataset = dh.getGroceries();
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) rv;
recyclerView.setLayoutManager(new LinearLayoutManager(context));
adapter = new GroceryListRecyclerViewAdapter(dataset,mListener,this);
recyclerView.setAdapter(adapter);
ItemTouchHelper.Callback callback = new SimpleTouchHelperCallback(adapter);
ith = new ItemTouchHelper(callback);
ith.attachToRecyclerView(recyclerView);
DividerItemDecoration div = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(div);
if (dataset.isEmpty()){
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
} else {
recyclerView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
}
return view;
}
Add a textview to your layout. At the same level as the RecyclerView
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<TextView
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:text="#string/no_data_available" />
At the onCreate or the appropriate callback check to see if the dataset that feeds your RecyclerView is empty. If it is then the RecyclerView is empty too. In that case, the message appears on the screen. If not, change its visibility:
private RecyclerView recyclerView;
private TextView emptyView;
// ...
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
emptyView = (TextView) rootView.findViewById(R.id.empty_view);
// ...
if (dataset.isEmpty()) {
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
}
else {
recyclerView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
}
This answer is for developers using Kotlin and databinding in their Android project.
custom_recyclerview_empty_support.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Recycler view -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Empty view -->
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/empty_text_view"
style="#style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/white_light"
android:gravity="center"
android:textColor="#color/black_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Empty View" />
<!-- Retry view -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/retry_linear_layout_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/white_light"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/retry_text_view"
style="#style/TextAppearance.MaterialComponents.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/views_pad_horizontal"
android:layout_marginTop="#dimen/views_pad_vertical"
android:layout_marginEnd="#dimen/views_pad_horizontal"
android:layout_marginBottom="#dimen/views_pad_vertical"
android:gravity="center"
tools:text="Retry View" />
<com.google.android.material.button.MaterialButton
android:id="#+id/retry_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/retry_button" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Loading view -->
<FrameLayout
android:id="#+id/loading_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/white_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ProgressBar
android:id="#+id/progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
The fragment class where I am using this Custom RecyclerView class
<app.ui.widgets.RecyclerViewEmptySupport
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Creating a Custom RecyclerView class :
class RecyclerViewEmptySupport(context: Context, attrs: AttributeSet) :
ConstraintLayout(context, attrs) {
private val binding: CustomRecyclerviewEmptySupportBinding
val recyclerView: RecyclerView
init {
this.binding =
CustomRecyclerviewEmptySupportBinding.inflate(LayoutInflater.from(context), this, true)
this.recyclerView = binding.recyclerView
}
fun updateViews(
loading: Boolean = false,
retry: Boolean = false,
empty: Boolean = false,
success: Boolean = false
) {
binding.recyclerView.setVisibleOrGone(success)
binding.emptyTextView.setVisibleOrGone(empty)
binding.retryLinearLayoutView.setVisibleOrGone(retry)
binding.loadingView.setVisibleOrGone(loading)
}
// Empty view
fun showEmptyMessage(message: String) {
updateViews(empty = true)
binding.emptyTextView.text = message
}
// Retry view
fun showRetryView(message: String, callback: () -> Unit) {
updateViews(retry = true)
binding.retryTextView.text = message
binding.retryButton.setOnClickListener { callback() }
}
}
The Fragment/Activity class can manage the Views visibility and setting data to views , like this :
When api is to be called , call this block of code ,
binding.myRecyclerView.updateViews(loading = true)
getDataFromRepository()
When data is empty in api response , call this,
binding.myRecyclerView.showEmptyMessage("No Items Message")
When data exists in api , call this ,
list.addAll(apiList)
adapter.notifyDataSetChanged()
binding.myRecyclerView.updateViews(success = true)
When there is some error in api response , call this
binding.myRecyclerView.showRetryView("Unable to get data at the moment.") { getDataFromRepository() }
Why don't you go for a Relative layout.
<Relative layout>
<Recycler View/>
<Text View/>
</Relative layout
As the array is empty
RecyclerView.GONE
TextView.VISIBLE
and if the array is having some data
RecyclerView.VISIBLE
TextView.GONE
In my case, I am following this only.
If doesn't work, I'll send you my code.
When I faced this issue, while surfing the web I found useful gist https://gist.github.com/sheharyarn/5602930ad84fa64c30a29ab18eb69c6e.
Here shown how to implement empty view in elegant way by defining data observer.

android soft keyboard overlays the edittext in recyclerview in bottomsheet

I have a few EditText in RecyclerView that is inside of a BottomSheetDialog. The problem I have now is that when BottomSheetDialog is shown on the screen, I tap on for example the 7th EditText in the RecyclerView. Soft keyboard appears and overlays the EditText, so I can't see what I type. but if I dragged the BottomSheetDialog a bit up, EditText then won't be covered by soft keyboard even if I tap on last EditText on the screen. RecyclerView is definitely resized in this case but doesn't resize if I didn't drag BottonSheetDialog a bit up. any idea why? and how I can fix this?
this is how it looks like.
Main.java
class VH extends RecyclerView.ViewHolder {
public VH(View itemView) {
super(itemView);
}
}
private void test() {
BSTest bsTest = new BSTest(this);
bsTest.setContentView(R.layout.bottomsheet_test);
RecyclerView rv = (RecyclerView) bsTest.findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(new RecyclerView.Adapter() {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new VH(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_edittext, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 20;
}
});
bsTest.show();
}
BSTest.java
public class BSTest extends BottomSheetDialog {
public BSTest(#NonNull Context context) {
super(context);
}
private BSTest(#NonNull Context context, #StyleRes int theme) {
super(context, theme);
}
private BSTest(#NonNull Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
}
bottomsheet_test.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:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
item_edittext.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:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Using this KeyboardUtil as new solution !
Use this in onCreateDialog in BottomSheetFragment
KeyboardUtil(getActivity(), view);
or
For fragment use
new KeyboardUtil(this, findViewById(R.id.fragment_container));
by using this Util class
https://github.com/mikepenz/MaterialDrawer/blob/aa9136fb4f5b3a80460fe5f47213985026d20c88/library/src/main/java/com/mikepenz/materialdrawer/util/KeyboardUtil.java
Credit:Mikepenz
It looks that editing your Manifest and adding android:windowSoftInputMode="adjustResize" to <activity> tag of this activity should solve your problem.
Docs: https://developer.android.com/guide/topics/manifest/activity-element.html#wsoft

Categories

Resources