Im trying to add a view to my Material dialog using setView(...), I want to have my inflated view look like this
That is the recycler view will always take up roughly 2/3 of the screen. That includes when it is empty, where it will be an empty space and when it has many lines of data, where it can become scroll able.
This is my aim. However when I try to inflate this View inside my dialog I get the following..
That screen represents an empty recyclerview taking up most of the screen.
Here is the code
//Adding to dialog
mMaterialDialog = new MaterialDialog(mContext)
.setView(new ISEQDialog(mContext))
//.setBackgroundResource(R.drawable.dublin_watchlist)
.setPositiveButton("OK", new View.OnClickListener() {
#Override
public void onClick(View v) {
mMaterialDialog.dismiss();
}
});
mMaterialDialog.show();
}
});
//View
public class ISEQDialog extends FrameLayout{
SeekBar mBuySeekBar;
TextView mStockHeading;
Context mContext;
View mView;
RecyclerView mStockDataList;
public ISEQDialog(Context context) {
super(context);
this.mContext = context;
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(inflater != null){
mView = inflater.inflate(R.layout.stock_dialog, null);
}
mStockDataList = (RecyclerView) mView.findViewById(R.id.rv_stock_data_list);
//
mStockDataList.setAdapter(new ISEQDialofRecyclerViewAdapter());
LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
mStockDataList.setLayoutManager(layoutManager);
//mStockDataList.addItemDecoration(new DividerItemDecoration(mContext.getDrawable(R.drawable.divider)));
addView(mView);
}
}
//RecyclerViewAdapter
public class ISEQDialofRecyclerViewAdapter extends RecyclerView.Adapter<ISEQDialofRecyclerViewAdapter.ViewHolder>{
#Override
public ISEQDialofRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
#Override
public void onBindViewHolder(ISEQDialofRecyclerViewAdapter.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 0;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
//XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_stock_dialog_heading"
android:layout_weight="0.2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:textColor="#color/list_divider_pressed"
android:layout_gravity="top"
android:background="#null"
android:textSize="35dp"
android:text="Portfolio Value"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_stock_data_list"
android:layout_weight="0.7"
android:layout_height="0dp"
android:divider="#drawable/list_selector"
android:dividerHeight="1dip"
android:layout_width="match_parent">
</android.support.v7.widget.RecyclerView>
<SeekBar
android:id="#+id/sb_buy_stocks"
android:layout_weight="0.1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:indeterminate="false" />
</LinearLayout>
I had the same issue trying to add the recycler view to the dialog.
When i tried troubleshooting i realized that only the constrcutor of the recycler view adapter gets called and stops. The remaining methods as getItemCount(), onCreateViewHolder() and onBindViewHolder() doesn't gets called.
So i did the following
1) i replaced the recyclerview with the linear layout.
2) referenced the linear layout as view holder in code.
3) Then i manually iterated through the list i was to pass to the recycler view and on so i inflated the single row xml file, referenced the views and set text on it.
4) I added the view to the view holder and displayed the dialog. It works
5) This operation inflates the view as we are not recycling anything so if the items to display is below 10-15 you can use this as well or else hits the performance of the app a slight.
In Activity
Dialog myTestDialog = new Dialog(getActivity());
myTestDialog.setContentView(R.layout.order_details_orders_to_deliver);
//get the layout group
ViewGroup layout = (ViewGroup) myTestDialog.findViewById(R.id.order_details_recycler_view);
List<OrderItemDetails> orderItemDetailsList = mDatabaseOperationsAdapter.getOrderDetail(ordersToDeliver.getOrderId());
for (int x = 0; x < orderItemDetailsList.size(); x++) {
OrderItemDetails orderItemDetails = orderItemDetailsList.get(x);
View view = inflater.inflate(R.layout.order_details_row, null);
TextView itemName = (TextView) view.findViewById(R.id.order_details_item_name);
TextView quantity = (TextView) view.findViewById(R.id.order_details_item_quantity);
TextView itemTotal = (TextView) view.findViewById(R.id.order_details_item_total);
itemName.setText(orderItemDetails.getProductName());
quantity.setText(String.valueOf(orderItemDetails.getProductQuantity()));
itemTotal.setText(String.valueOf(orderItemDetails.getTotalPrice()));
layout.addView(view);
}
myTestDialog.show();
Note : order_details_recycler_view is the linear layout not recycler view as i changed it to linear layout keeping the id same.
List orderItemDetailsList is the list that was to be passed to the adapter.
This problem is related to RecyclerView as i know, when it is empty it fills layout, unless you give fixed layout_height.
There is trick, which is you check list of items before you create alertDialog. If empty, create alertDialog without RecyclerView, just with warning text. Otherwise create your custom alertDialog.
Related
Here is what I am trying to do:
What is the simplest way to create rows that scroll together and are composed of variable sized clickable Views with the same height on Android
Basically create variable width columns that have the same width in every row. Also need to add, delete and add listeners. Seems like a fairly simple task, but I am finding Android's GUI library a lot harder to figure out than Java's and WPF's GUI library.
Here is my RecyclerView:
public class MainActivity extends AppCompatActivity {
private RecyclerView ampRecyclerView;
private RecyclerView.Adapter ampAdapter;
private RecyclerView.LayoutManager ampLayoutManager;
List<FunctionView> myDataset = new ArrayList<FunctionView>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpRecyclerView();
}
private void setUpRecyclerView() {
LinearLayout linearLayout = findViewById(R.id.main_ll);
linearLayout.setWillNotDraw(false);
ampRecyclerView = (RecyclerView) findViewById(R.id.AmpRecyclerView);
// use a linear layout manager
ampLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
ampRecyclerView.setLayoutManager(ampLayoutManager);
myDataset.add(new FunctionView(this));
myDataset.add(new FunctionView(this));
myDataset.add(new FunctionView(this));
// specify an adapter
ampAdapter = new MainActivityAdapter(myDataset, 1);
ampRecyclerView.setAdapter(ampAdapter);
}
}
My adapter
class MainActivityAdapter extends RecyclerView.Adapter<MainActivityAdapter.FunctionViewHolder> {
private List<FunctionView> views = new ArrayList<FunctionView>();
private List<LinearLayout> llViews = new ArrayList<>();
private int rows;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class FunctionViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public LinearLayout linearLayout;
public FunctionViewHolder(LinearLayout v) {
super(v);
linearLayout = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MainActivityAdapter(List<FunctionView> myDataset, int rows) {
views = myDataset;
this.rows = rows;
}
// Create new views (invoked by the layout manager)
#Override
public MainActivityAdapter.FunctionViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
LinearLayout linearLayout = (LinearLayout) LayoutInflater.from(parent.getContext())
.inflate(R.layout.function_holder, parent, false);
llViews.add(linearLayout);
MainActivityAdapter.FunctionViewHolder vh = new MainActivityAdapter.FunctionViewHolder(linearLayout);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MainActivityAdapter.FunctionViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
int width = 0;
for(FunctionView fv : views){
holder.linearLayout.addView(fv);
width += fv.getWidth();
}
holder.linearLayout.setMinimumWidth(width);
//TODO set the data
// holder.functionView = views.get(position);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return rows;
}
I know there are glaring design flaws. I am trying to get the scrolling working first, because every layout I try doesn't work how I'd like.
Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_ll"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/AmpRecyclerView"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
and the holder:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:isScrollContainer="true"
android:nestedScrollingEnabled="true"
>
</LinearLayout>
as you said there are glaring design flaws, but you need to change the android:layout_height to wrap_content and android:layout_width to match_Parent.
if your item's hight is match_parent then your inner layout's hight becomes the recyclerview's hight then there is no room for other items so there will be no scrolling.
also, put something like a textView in it to be able to see the items.
another note, the name is supposed to be item not holder. holder is related to ViewHolder which is a totally different thing. you can name it according to your activity for example if Your activity name is MainActivity so your activity layout is activity_main, then you can call the inner layouts item_main
I recommend watching a tutorial on youtube or read an article from medium or anywhere (you can simply just google android recyclerview example) to learn the basics.
<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:id="#+id/txt_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SAMPLE"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:textSize="30sp"
/>
</LinearLayout>
I am using a recycler view to show some data. When the app is launched it looks correct as follows with wrap content for height. After I scroll past the last item, I am able to keep scrolling and the data is no longer wrapped, looking like match parent instead for height. Scrolling back up, everything has changed to match parent for the height.
Using past references here, I have tried with ConstraintLayouts and switched height wrapping between the parent layout and the recyclerview itself. Both doesn't help. I am guessing this has to do more with the xml. Please advice.
This is what I expect to always get. This is what I current get when app launches, but changes after I scroll to last item.
When I scroll to last item this happens.
Now if I scroll back up, the height is no longer wrapped. Everything seems to have changed to match parent.
This is xml for the custom view I am using to inflate.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/feed_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/feed_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp"
tools:text="Test Title" />
<TextView
android:id="#+id/feed_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="#+id/feed_title"
tools:layout_editor_absoluteX="0dp"
android:layout_below="#+id/feed_title"
tools:text="This is some random description for testing purposes. Other wise just typing on to create more stuff..." />
</RelativeLayout>
This is layout for the Recycler View which is placed on a Fragment activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context=".fragment.CurrentFeedFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/current_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
This is over at my FragmentActivity where I am loading the data for the RecyclerView.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_current_feed, container, false);
initiateTestData();
loadDataToRecyclerView(view);
return view;
}
private void initiateTestData(){
testTitles = new ArrayList<>();
testDescriptions = new ArrayList<>();
for (int i = 5; i < 25; i++) {
testTitles.add("title " + i);
testDescriptions.add("This is some random description for testing purposes. Other wise just typing on to create more stuff... " + i);
Log.d(TAG, "initiateTestData: " + "title " + i);
}
}
private void loadDataToRecyclerView(View v){
Log.d(TAG, "loadDataToRecyclerView: " + testTitles.size());
RecyclerView recyclerView = v.findViewById(R.id.current_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
FeedAdapter adapter = new FeedAdapter(testTitles, testDescriptions, getActivity());
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
Don't think this is relevant. But for reference, this is my adapter class.
public class FeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private static final String TAG = "FeedAdapter";
private List<String> titles;
private List<String> descriptions;
private Context context;
public FeedAdapter(List<String> titles, List<String> descriptions, Context context) {
this.titles = titles;
this.descriptions = descriptions;
this.context = context;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_current_feed, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
final ViewHolder holder = (ViewHolder) viewHolder;
holder.feedTitle.setText(titles.get(i));
holder.feedDescription.setText(descriptions.get(i));
holder.layout.setOnClickListener(v -> {
Log.d(TAG, "Clicked: " + titles.get(i));
Toast.makeText(context, titles.get(i), Toast.LENGTH_SHORT).show();
});
}
#Override
public int getItemCount() {
return titles.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView feedTitle;
TextView feedDescription;
RelativeLayout layout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
feedTitle = itemView.findViewById(R.id.feed_title);
feedDescription = itemView.findViewById(R.id.feed_description);
layout = itemView.findViewById(R.id.feed_layout);
}
}
}
Your recycler view height is wrap_content
And recycler view item height match_parent
I would think you'd want them the other way around.
The RV's height = match_parent, i.e. the recycler view occupies all available height.
The RV item's height = wrap_content, i.e. each item only as tall as it needs to be, so that multiple items can fit.
i am facing a problem i cannot resolve. i googled it but couldnt get the solution im looking for. i have a recycle view as follow:
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:paddingBottom="70dp"
android:layout_marginTop="#dimen/activity_vertical_margin"
this recycle view is showing in the screen as follow
if you notice, there is no spacing above the text and bottom of the text for each item. most likely due to wrap_content. i want to add space within the item cell on top and bottom. something like this image
if you noticed, i draw red arrows to indicate the extra space and the text in the center of each item list. how can i add space within the cell(space on top of text and space on bottom of text? left and right space will be cool too.
when i googled this, i only found code to add spacing between items. but what i am looking for is to add spacing within the cell item itself like the second picture attach. i would appreciate your help. thanks in advance
Definitely you are using an adapter for your recycler view and that adapter is responsible to create children. As #cocored said you have to create your own layout. you have to do it in your adapter (usually in onCreateViewHolder).
you can use inflater service to inflate an xml layout for each child.
recyclerview_child.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="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"/>
...
</LinearLayout>
and in your adapter do something like this
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private List<Whatever> mData;
private LayoutInflater mInflater;
MyRecyclerViewAdapter(Context context, List<Whatever> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the child layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_child, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each child
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Whatever obj = mData.get(position);
holder.myTextView.setText(obj.getName());
...
}
// total number of children
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder{
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.tv);
}
}
}
hope it helps
You would have to add a padding to your recycler item. If you're using a default item layout from android I would suggest creating your own layout.
I have used RecyclerView several times before, but it is the first time that it is working too slow.
In this case, the items are represented by a simple LinearLayout with 3 views inside it:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/linearLayout"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvTicketNumber"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:padding="8dp"/>
<EditText
android:id="#+id/etTotalSold"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:padding="8dp"
android:gravity="center" />
<TextView
android:id="#+id/tvSurplus"
android:layout_width="0dp"
android:layout_weight="1"
android:padding="8dp"
android:layout_height="match_parent"
android:gravity="center"/>
</LinearLayout>
The RecyclerView uses the previous layout in its adapter:
public class TicketAdapter extends RecyclerView.Adapter<TicketAdapter.ViewHolder> {
private ArrayList<Ticket> dataSet;
// Define references to the views for each data item
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvTicketNumber, tvSurplus;
public EditText etQuantity;
public ViewHolder(View v) {
super(v);
tvTicketNumber = (TextView) v.findViewById(R.id.tvTicketNumber);
etQuantity = (EditText) v.findViewById(R.id.etQuantity);
tvSurplus = (TextView) v.findViewById(R.id.tvSurplus);
}
}
public TicketAdapter() {
dataSet = new ArrayList<>();
}
public void setDataSet(ArrayList<Ticket> dataSet) {
this.dataSet = dataSet;
}
private String twoDigits(final int i) {
final String pre = (i<=9 ? "0" : "");
return pre + i;
}
#Override
public TicketAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.table_row, parent, false);
// set the view's size, margins, padding and layout parameters
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// get element from the data set
Ticket ticket = dataSet.get(position);
// replace the contents of the view with that element
holder.tvTicketNumber.setText(twoDigits(position));
holder.tvSurplus.setText("6");
}
#Override
public int getItemCount() {
return dataSet.size();
}
}
Before, I was using TableLayout with TableRows created programmatically, but I have read that layout have to be used for a defined number of rows in XML.
I have to load a list of 100 items in a fragment. But it takes approximately 4 seconds to load. For that reason I wrote some logic to show a progressBar and next hide it and show the scrollView (the recycler is within it).
The fragmentTransaction was still slow, so I moved the code to the onViewCreated method.
The transaction was still slow and I added an AsyncTask. With this last change, the transaction is faster, but the progressBar looks stopped all the time and the buttons can't be used (the onPostExecute is taking 4 seconds to load and show the recyclerView).
I want to show the animation of the progressBar, but the onPostExecute is executed in the UI thread and all the app is stopped for 4 seconds while the RecyclerView is loading.
Please give me some ideas. Before I have used items with images loaded from internet, and the RecyclerView was working faster. It is too strange.
I inflate another layout to appear below some view in my current layout.
This is done like this:
LayoutInflater vi = (LayoutInflater) getActivity().getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rootView = vi.inflate(R.layout.horizontal_scroll_view, null);
horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.hsv_suggestions_scroll_view);
LinearLayout suggestionsContainer = (LinearLayout) horizontalScrollView.findViewById(R.id.ll_suggestions_container);
and I can confirm that it appears in the right place since I add some Views in it after a while and they all appear.
The layout I inflate is :
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hsv_suggestions_scroll_view"
android:scrollbars="none" android:layout_gravity="center_horizontal"
android:paddingTop="16dp" android:fillViewport="true"
android:layout_width="match_parent" android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/ll_suggestions_container"
android:gravity="center_horizontal" android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</LinearLayout>
just a HorizontalScrollView with a LinearLayout as a child.
The Views I add later are all of them TextViews.
Now after a user action (write some text on an editText) I'm trying to scroll to that View and highlight it. Highlight works. What does not work is scroll.
I have tried :
horizontalScrollView.postDelayed(new Runnable() {
#Override
public void run() {
horizontalScrollView.smoothScrollTo(scrollTo, 0);
}
}, 300);
where variable scrollTo is what I get when I apply getLeft() to the View I wanna scroll to. I can confirm that it takes various values.
Anyone can help me with that ?
Got a similar issue.
I guess the root cause is that the UI was not yet rendered at that moment, causing the scroll not to work properly.
I just had to wrap my call to smoothScrollTo into .post as follows:
mScrollView.post(new Runnable() {
#Override
public void run() {
mScrollView.smoothScrollTo(xxx, yyy);
}
});
Notice that I do a post directly on the scrollView to make sure it is executed after it is being rendered. For example, doing a getActivity().runOnUIThread() would not work in my case.
Switch to using a RecyclerView with a LinearLayoutManager with orientation set to Horizontal. Like this:
scroll_view.xml
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/scrollView"
android:scrollbars="none"
android:layout_gravity="center_horizontal"
android:paddingTop="16dp"
android:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/scrollContainer"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.RecyclerView>
Note: the layoutManager tag is required here for the layout to inflate. After it's inflated, we're going to set it programatically as well because otherwise we'll get an exception because the RecyclerView basically disposes of it before it's done with it.
OptionAdapter.java
public class OptionAdapter extends RecyclerView.Adapter<OptionAdapter.OptionHolder> {
private Context context;
private LayoutInflater inflater;
private ArrayList<String> options;
public OptionAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
options = new ArrayList<>();
}
#Override
public OptionHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new OptionHolder(inflater.inflate(R.layout.textview, parent, false));
}
#Override
public void onBindViewHolder(OptionHolder holder, int position) {
String option = options.get(position);
((TextView) holder.itemView).setText(option);
}
#Override
public int getItemCount() {
return options != null ? options.size() : 0;
}
public ArrayList<String> getOptions() {
return options;
}
public void addOption(String option, Integer index) {
if (index != null && index <= options.size()) {
options.add(index, option);
} else {
options.add(option);
}
notifyDataSetChanged();
}
public class OptionHolder extends RecyclerView.ViewHolder {
public OptionHolder(View itemView) {
super(itemView);
}
}
}
text_view.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
Setting everything up
final LayoutInflater inflater = LayoutInflater.from(this);
final RecyclerView scrollView = (RecyclerView) inflater.inflate(R.layout.scroll_view, container, false);
scrollView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
final OptionAdapter adapter = new OptionAdapter(this);
scrollView.setAdapter(adapter);
container here is whatever view is going to be holding the RecyclerView. In my code, I've got it in a LinearLayout.
Adding a view to the list
adapter.addOption("The Added One", null);
Or if you want to add it to a specific position in the list.
adapter.addOption("The Added One", position);
Scrolling to a specific position
scrollView.smoothScrollToPosition(position);
Scrolling to a specific item in the list
scrollView.smoothScrollToPosition(adapter.getOptions().indexOf("ItemText"));
Hope it works for you!
Instead of smoothScrollTo(), try using scrollTo().
Make sure that your getLeft() is really returning a value > 0;