I have two text views side by side in my RecyclerView item. One of the views has layout_weight="1" to keep another view visible if the view is wide.
The problem is that the the view sizes are not updating when the views got recycled, so to textView id:name width is not correct when i scroll the list.
Should I somehow force the view to update the layout?
My RecyclerView item:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1" />
<LinearLayout
android:id="#+id/code_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#drawable/background_code"
android:orientation="vertical">
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"/>
</LinearLayout>
</LinearLayout>
Im using RecyclerView v. 23.4.0.
Update
1. I have tried to call my RecyclerView item layout root requestLayout at the end of the adapter onBindViewHolder().
This does not any have affect, my views are not updated.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
...
viewHolder.mLayoutRoot.requestLayout();
}
2. Maybe the problem is that the view is not yet completely drawn when I call requestLayout? So I tried to set GlobalLayoutListener and call requestLayout there. I think this helps little, but still if I have enough items, in my list not all views are updated. Owerall in my list I have around max 10 items.
ViewTreeObserver vto = viewHolder.mLayoutRoot.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
viewHolder.mLayoutRoot.requestLayout();
}
});
3. I tried to use TableLayout with shrinkColumns property to approach similar layout, but the result is same. Name text view widht is not always correctly set. Also, it looks like requestLayout has no affect at all (or am I calling it in wrong place?)
4. (28/8/2016)
I stripped down my code to bare minimum to reproduce this.
I managed to fix this using setIsRecyclable(false), like dosssik suggests, but I think it is not very good solution in terms of performance?
Here is my full list item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_marginLeft="16dp"
android:orientation="horizontal">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1" />
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_stop_code_small"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"
android:textSize="11sp"/>
</LinearLayout>
My adapter code:
I also tried to call invalidate(), but can not see any affect.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Item item = getItem(position);
NormalViewHolder viewHolder = (NormalViewHolder) holder;
viewHolder.mName.setText(item.getName());
//viewHolder.mName.invalidate(); // No help
viewHolder.mCode.setText(item.getCode());
//viewHolder.mCode.invalidate(); // No help
}
Expected behaviour:
+----------------------------------------+
|[Name][Code] |
+----------------------------------------+
|[Name qwertyuiopasdfghjklzxcvb...][Code]|
+----------------------------------------+
This is how works right now if I scroll list up/down. So the layout is not updated and code is not alignet right to name. Also name is not taking always enough space.
+----------------------------------------+
|[Name][Code] |
+----------------------------------------+
|[Name qwer...] [Code] |
+----------------------------------------+
|[Name qwertyuiopa][Code] |
+----------------------------------------+
|[Name qwe] [Code] |
+----------------------------------------+
I share my solution which is not need to use
setIsRecyclable(false)
Use below custom TextView at your xml.
public class TextViewForRecyclerView extends android.support.v7.widget.AppCompatTextView {
public TextViewForRecyclerView(Context context) {
super(context);
}
public TextViewForRecyclerView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public TextViewForRecyclerView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
requestLayout();
}
}
This xml works for me without using setIsRecyclable(false);
In some android versions (like kitkat) the code: android:ellipsize="end" only works with android:singleLine="true", so add this to the first TextView "#+id/name" and it will works!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_marginLeft="16dp"
android:orientation="horizontal">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:maxLines="1"
/>
<TextView
android:id="#+id/code"
android:layout_weight="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_stop_code_small"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"
android:textSize="11sp"/>
</LinearLayout>
The result:
As it seems code is of constant length, you can use following UI deisgn;
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:gravity="center_vertical">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:align_parentLeft="true"
android:layout_toLeftOf="#+id/code"
android:layout_marginRight="8dp"
android:ellipsize="end"
android:maxLines="1" />
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_code"
android:gravity="center"
android:align_ParentRight="true"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"/>
</RelativeLayout>
The RecyclerView will reuse ViewHolder objects so the layouts of those will be inflated once and then reused through the lifetime of the list. Try calling requestLayout on your root LinearLayout.
Usage of forceLayout(), requestLayout() and invalidate()
You need to invalidate the two TextView views, and make sure you are doing it after you set the new text value to them:
#Override
public void onBindViewHolder(ItemHolder holder, int position)
{
...
holder.nameTextView.invalidate();
holder.codeTextView.invalidate();
}
As an alternative, if you don't mind the code view aligning to the right, you could replace the LinearLayout for a RelativeLayout and set the proper constraints between the name view and the code container:
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/code_container"
android:layout_toStartOf="#+id/code_container"
android:ellipsize="end"
android:maxLines="1" />
<LinearLayout
android:id="#+id/code_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="#drawable/background_code"
android:orientation="vertical">
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"/>
</LinearLayout>
I had very simillar problem with recyclerView.
Sometimes it works not properly, when items recycling, unfortunatly.
for me helped turning off recyclable.
setIsRecyclable(false);
you can do it in ViewHolder's constuctor like this:
class Holder extends RecyclerView.ViewHolder {
public Holder(View itemView) {
super(itemView);
setIsRecyclable(false);
}
}
Sure, that not awesome solution, but it's the only solution, that helped me.
Hope it will help you.
I finally got the right answer. As my test, you can just add two lines in you method onBindViewHolder, as below:
#Override
public void onBindViewHolder(ItemHolder holder, int position)
{
holder.mName.setSingleLine(false); //first line
holder.mName.setText("name");
holder.mCode.setText("");
holder.mName.setSingleLine(true); //second line
}
Hope it help you.
you should add weight to inner linear layout also then it will be
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="2"
android:ellipsize="end"
android:maxLines="1" />
<LinearLayout
android:id="#+id/code_container"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#drawable/background_code"
android:orientation="vertical">
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"/>
</LinearLayout>
try this will work for you
I have had layout refresh problems in a chat-like Activity using RecyclerView: I've called a method from onBindViewHolder to adapt any chat message's margins, below a code snippet:
..
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) this.mItemView.getLayoutParams();
lp.setMargins(0,0,50,0);
try this i am not use editor but it will auto-correct if any problem with xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" //i changed this
android:layout_height="150dp"
android:layout_marginLeft="16dp"
android:weightsum="1"//added this
android:orientation="horizontal">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true" />//added this
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_stop_code_small"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"
android:textSize="11sp"/>
</LinearLayout>
the above will work
if you still insist of updating layout, always know if the update you need is measurement then you need to call View.invalidate() along with View.requestLayout()
Try using this, I had same issue, i resolved it using this :
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View rootView = LayoutInflater.from(context).inflate(R.layout.review_data, null, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(lp);
return new ViewHolder(rootView);
}
Set layout params in onCreateViewHolder like above.
setting weight on just one of them is wrong, because when the code is long the name will get disappeared.
I don't know what are you trying to achieve, but even with a simple ListView and a simple layout like below for its items they will never get disappeared and I think they look better:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:gravity="left"
android:layout_marginLeft="16dp"
android:orientation="horizontal">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:layout_marginRight="8dp"
android:ellipsize="end"
android:text="dfsdd45te5sf"
android:maxLines="1" />
<TextView
android:id="#+id/code"
android:layout_weight=".5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_green_dark"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:layout_marginRight="1dp"
android:text="ertertete5tte5tte5e5te5t"
android:singleLine="true"
android:textSize="12sp"/>
</LinearLayout>
I think you are expecting Out put simile like this
in the top container LinearLayout change "wrap_content" to "match_parent"
check this tutorial
http://wiki.workassis.com/android-recyclerview-example/
Well, I am not getting exact problem what you are facing...but one problem i can
see in your code is weight, you are using weight in a wrong way. weight will not effective if you use in one widget, at-least you have to use two widget to give proper weight between them, and use weight sum in their parent to work properly. for example see below your modified code:-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="3">
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:text="qwertyuioopasdfsd" />
<LinearLayout
android:id="#+id/code_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="2"
android:background="#drawable/background_code"
android:orientation="vertical">
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp" />
</LinearLayout>
</LinearLayout>
Related
I have layouts which will be repetitive added in main layout:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/txt_temp_feels_like"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-medium"
android:text="-"
android:textColor="#color/gray"
android:textSize="18sp" />
I want it to be added to this container:
<LinearLayout
android:id="#+id/temp_feels_like_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:orientation="horizontal">
</LinearLayout>
And I want to do it in code. I'm using this method:
private fun setData(
layout: List<Int>,
container: List<ViewGroup>,
) {
for (i in layout.indices) {
container[i].addView(layoutInflater.inflate(layout[i], null))
}
}
where layout is link to resource of layout.
And it's fill it but i have some problems:
I can't set text to this added view
I can't set weight to this view
Maybe my algorithm is wrong. Can you help?
It depends on when should you set the text and gravity. If you can set it before adding to layout - you can do something like that:
val view = layoutInflater.inflate(layout[i], null) as TextView
view.apply {
text = "abc"
params = (params as LinearLayout.LayoutParams).apply {
weight = *value you need*
}
}
container[i].addView(view)
Or if you need to set text to view after views are added to layout, you can reference to view via container.children/container.getChildAt(i)
UPD
you can get the child in the following way:
val count = layout.getChildCount()
var v: TextView? = null
for (i in 0..count) {
val view = layout.getChildAt(i)
if (view is TextView) {
v = view
}
}
Or one more way - set tag to view while adding it to layout and then you can get it by tag in any time you need
Could something like this help?
<LinearLayout
android:id="#+id/temp_feels_like_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginEnd="20dp"
android:layout_marginStart="20dp"
android:orientation="horizontal"
>
<TextView
android:id="#+id/txt_temp_feels_like1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-medium"
android:visibility="gone"
android:text="-"
android:textColor="#color/gray"
android:textSize="18sp"
/>
<TextView
android:id="#+id/txt_temp_feels_like2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-medium"
android:visibility="gone"
android:text="-"
android:textColor="#color/gray"
android:textSize="18sp"
/>
<TextView
android:id="#+id/txt_temp_feels_like3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-medium"
android:visibility="gone"
android:text="-"
android:textColor="#color/gray"
android:textSize="18sp"
/>
<TextView
android:id="#+id/txt_temp_feels_like4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-medium"
android:visibility="gone"
android:text="-"
android:textColor="#color/gray"
android:textSize="18sp"
/>
</LinearLayout>
You can have the gravity set appropriately (and the text if it's not dynamic),
and then set the visibility in code rather than try to add the view.
findViewById<View>(R.id.txt_temp_feels_like1).visibility = View.VISIBLE
I need to have like several listviews on a scrollview which Android doesn't allow me to do so I decided to make it manually to simply inflate some listrows on a vertical LinearLayout, but everything goes not the right way
private void fillData(final ViewGroup parent, final ArrayList<Person> array ){
for (int i=0;i<array.size();i++){
final View view = lf.inflate(R.layout.personal_listrow, parent,true);
parent.setBackgroundColor(getActivity().getResources().getColor(R.color.background_light_darker));
view.setBackgroundColor(getActivity().getResources().getColor(R.color.background_night_lighter));
TextView tvName=(TextView) view.findViewById(R.id.tvName);
TextView tvStatus=(TextView) view.findViewById(R.id.tvStatus);
TextView tvGender=(TextView) view.findViewById(R.id.tvGender);
//fill textviews with info, set the onClickListeners and so on
}
So what I get - the view.setBackgroundColor paints parent as well .
parent is a vertical LinearLayout, view is horizontal LinearLayout - it's strange that I don't paint inflated element only so please explain me why
The next thing - after I add something to array - 1st element changes and all the rest is with unchanged text. However, I walked through the code with debugger - it passes every element and sets text.
The clicklisteners works on the 1st element only..
Would you plz explain
here's vertical , parent layout - nothing special:
<LinearLayout
android:id="#+id/rodll"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
the inflateable listrow is nothing special also :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvStatus"
android:layout_width="0dp"
android:layout_weight=".3"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvSt" />
<TextView
android:id="#+id/tvName"
android:layout_weight="1"
android:layout_width="0dp"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvName" />
<TextView
android:id="#+id/tvGender"
android:layout_weight=".1"
android:layout_width="0dp"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvGender" />
<com.andexert.library.RippleView
android:id="#+id/removeRipple"
xmlns:ripple="http://schemas.android.com/apk/res-auto"
android:layout_marginLeft="30dp"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="7.5dip"
android:padding="3dp"
ripple:rv_alpha="255"
ripple:rv_zoom="true"
ripple:rv_zoomScale="0.8"
ripple:rv_type="rectangle">
<ImageView
android:id="#+id/remove_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/remove" />
</com.andexert.library.RippleView>
<com.andexert.library.RippleView
android:id="#+id/addRipple"
xmlns:ripple="http://schemas.android.com/apk/res-auto"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="7.5dip"
android:padding="3dp"
ripple:rv_alpha="255"
ripple:rv_zoom="true"
ripple:rv_zoomScale="0.8"
ripple:rv_type="rectangle">
<ImageView
android:id="#+id/add_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/add" />
</com.andexert.library.RippleView>
</LinearLayout>
So. what's the problem and how to solve it?
I've got a ListActivity with a custom Adapter. This adapter uses the following list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/ll1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin"
android:contentDescription="#string/checkbox_content_description"
android:src="#drawable/checkbox_unchecked"
android:background="#layout/transparent_background"
android:focusableInTouchMode="false"
android:adjustViewBounds="true"
android:clickable="false"
android:focusable="false" />
<TextView
android:id="#+id/tv_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin">
<TextView
android:id="#+id/tv_product_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
</LinearLayout>
<TextView
android:id="#+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
</LinearLayout>
<LinearLayout
android:id="#+id/ll2"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_below="#id/ll1">
<Space
android:id="#+id/filler_space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/default_margin"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginBottom="#dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false" />
<EditText
android:id="#+id/et_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginBottom="#dimen/default_margin"
android:inputType="number" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginBottom="#dimen/default_margin"
android:padding="0dp">
<AutoCompleteTextView
android:id="#+id/actv_search_product"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:singleLine="true"
android:ellipsize="end"
android:inputType="text" />
</LinearLayout>
<EditText
android:id="#+id/et_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/default_margin"
android:layout_marginBottom="#dimen/default_margin"
android:inputType="numberDecimal"
android:digits="0123456789.,-" />
</LinearLayout>
</RelativeLayout>
In the Adapter's getView-method I've added the following piece of code:
// Change the width of the Filler-Space to match the Image
// and leave the height as is
Space space = (Space) view.findViewById(R.id.filler_space);
space.setLayoutParams(new LinearLayout.LayoutParams(
imageView.getMeasuredWidth(), space.getMeasuredHeight()));
This gives the following result at first:
When I change the Visibility of my second LinearLayout (ll2) to VISIBLE, it gives the following result:
What I want instead is:
As it seems the Space-View width isn't changed at all.. While I know for fact that the getView methods are successfully called thanks to Log-messages and other things I do in the getView method.
Does anyone know what I did wrong?
PS: When I use View instead of Space I have the same result. Never used Space before, so I thought it might have to do something with that.
Solution thanks to Demand's option 4:
// Since we can't access Measured widths and heights before the View is completely loaded,
// we set up an Observer that will be called once the ListItem's layout is ready
ViewTreeObserver observer = view.getViewTreeObserver();
if(observer.isAlive()){
// In order to access the view in the onGlobalLayout, it needs to be final, so we create a final copy here
final View v = view;
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// This will be called once the layout is finished, prior to displaying it
#Override
public void onGlobalLayout() {
ImageView imageView = (ImageView) v.findViewById(R.id.image);
Space space = (Space) v.findViewById(R.id.filler_space);
// Change the width of the Filler-Space to match the Image and leave the height as is
space.setLayoutParams(new LinearLayout.LayoutParams(imageView.getMeasuredWidth(), space.getMeasuredHeight()));
}
});
}
You set width and height if your space to wrap_content. It's mean that space will have width as their children, but there is no children and you have width = 0. It's not about space, it's about layout measuring in android.
When you call your code:
Space space = (Space) view.findViewById(R.id.filler_space);
space.setLayoutParams(new LinearLayout.LayoutParams(
imageView.getMeasuredWidth(), space.getMeasuredHeight()));
Your imageView havn't measured yet and return width = 0. It will measured later before drawing. In getView() in adapter you only create views, but measuring, layout and drawing will be later.
You have several ways to fix it:
set width of your space in dp, instead of wrap_content.
using relative layout instead of three linear layouts.
Use TableLayout.
add GlobalTreeObserver and getMeasuredWidth() at right time.
Post your runnable to view's handler to get width after drawing.
I think the best ways is 2 and 3, because 4 and 5 will cause measuring several times.
Four views are using same xml. I want to show a linear layout for view 1 only.
I put android:visibility="gone" in xml. And then I am doing the following for view 1-
LinearLayout layone= (LinearLayout) view.findViewById(R.id.layone);
layone.setVisibility(View.VISIBLE);
But that doesn't set the visibility to visible.
Isn't it possible to show the view once its declared GONE in xml ?
I don't want to converse the logic by just doing,
layone.setVisibility(View.GONE);
in each of the three views except view 1.
Ideas or comments?
UPDATE:
My xml -
<TextView
android:id="#+id/layone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Previous Page"
android:textColor="#000000"
android:textSize="16dp"
android:paddingLeft="10dp"
android:layout_marginTop="10dp"
android:visibility="gone" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:padding="10dp"
android:gravity="center_vertical"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:tag="PrevEntries"
android:id="#+id/laytwo"
android:layout_marginTop="10dp"
android:background="#layout/roundedtext"
android:visibility="gone" >
<TextView
android:id="#+id/laythree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Previous Page"
android:textColor="#000000"
android:textSize="18dp"
android:gravity="center"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="#+id/layone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Previous Page"
android:textColor="#000000"
android:textSize="16dp"
android:paddingLeft="10dp"
android:layout_marginTop="10dp"
android:visibility="gone" />
layone is a TextView.
You got your id wrong.
LinearLayout layone= (LinearLayout) view.findViewById(R.id.laytwo);// change id here
layone.setVisibility(View.VISIBLE);
should do the job.
or change like this to show the TextView:
TextView layone= (TextView) view.findViewById(R.id.layone);
layone.setVisibility(View.VISIBLE);
Done by having it like that:
view = inflater.inflate(R.layout.entry_detail, container, false);
TextView tp1= (TextView) view.findViewById(R.id.tp1);
LinearLayout layone= (LinearLayout) view.findViewById(R.id.layone);
tp1.setVisibility(View.VISIBLE);
layone.setVisibility(View.VISIBLE);
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/activity_register_header"
android:minHeight="50dp"
android:orientation="vertical"
android:visibility="gone" />
Try this piece of code..For me this code worked..
Kotlin Style way to do this more simple (example):
isVisible = false
Complete example:
if (some_data_array.details == null){
holder.view.some_data_array.isVisible = false}
put this attribute in your xml view for Gone
android:visibility="gone"
put this attribute in your xml view for Show
android:visibility="visible"
Example
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/futura_medium_bt"
android:text="•Unlock all graphics"
android:textAllCaps="true"
android:visibility="gone"
android:textColor="#color/black"
android:textSize="#dimen/_12ssp" />
I have a default ListView that i have added my custom views for the list items, but the buttons inside of these views are not clickable most of the time. I output a Log.v when the button receives a click event, but i have to tap the button almost a dozen times before it will register the click.
The other problem related tot his that i am having is that when the button is pressed i want an animation to happen revealing a menu sliding out from beneath it. At the moment i have tried several different methods like making a custom class for the views versus just using a layout inflater to get the relativeLayout object for the view, but nothing is working properly. I have even tried using listview.getAdapter().notifyDataSetChanged(); but that only has a pop-into-place for the extended view when i want an animation.
I have searched everywhere and it seems like the only possible solutions are to either rewrite my own custom listview or to use a linearlayout with a scrollview. The latter seems easier but i dont think it is nearly as optimized as the listview is.
Any suggestions would be greatly appreciated, if you need to see some code, please let me know...
Thanks!
UPDATE:
the getView() contains this:
Holder hold;
convertView = friends.get(position);
hold = new Holder();
hold.pos = position;
convertView.setTag(hold);
return convertView;
basically i pass an ArrayList<RelativeLayout>, at the moment, to the Adapter so that i dont have to create a new view each time and so that the animation will stay animated when i scroll down...
inside the OnCreate() for this activity i set that ArrayList<RelativeLayout> with this next code, but this is only temporary as i plan to use another method later, like an Async task or something so that this view contains some data...
RelativeLayout temp;
for(int i=0; i<30; i++){
temp = (RelativeLayout) inflater.inflate(R.layout.list_item, null);
final LinearLayout extraListItemInfo = (LinearLayout) temp.findViewById(R.id.extraListItemInfo);
Button infoBtn = (Button) temp.findViewById(R.id.infoBtn);
infoBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Log.v("ListItem", "Button has been clicked... ");
extraListItemInfo .setVisibility(View.VISIBLE);
ExpandAnimation closeAnim = new ExpandAnimation(extraListItemInfo , animHeight);
closeAnim.setDuration(750);
closeAnim.setFillAfter(true);
if(extraListItemInfo .getTag() == null || !extraListItemInfo .getTag().equals("expanded")){
extraListItemInfo .getLayoutParams().height = 0;
friendInfoList.startAnimation(closeAnim.expand());
extraListItemInfo .setTag("expanded");
}else if(extraListItemInfo .getTag().equals("expanded")){
extraListItemInfo .startAnimation(closeAnim.collapse());
extraListItemInfo .setTag("closed");
}
//((BaseAdapter) listview.getAdapter()).notifyDataSetChanged(); i tried it here once but then left it
//as the only action inside the listview's onitemclick()
}
});
listItems.add(temp);
}
this is the list item that i am using:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/darkgrey"
android:paddingBottom="5dp" >
<LinearLayout
android:id="#+id/extraListItemInfo "
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/listItemInfo"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="-10dp"
android:background="#color/grey"
android:orientation="vertical"
android:visibility="gone" >
<RelativeLayout
android:id="#+id/RelativeLayout04"
android:layout_width="match_parent"
android:layout_height="#dimen/activity_list_height"
android:layout_marginTop="5dp" >
<ImageView
android:id="#+id/ImageView04"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_margin="5dp"
android:src="#drawable/logo_d" />
<TextView
android:id="#+id/TextView04"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/ImageView04"
android:text="TextView"
android:textColor="#color/black"
android:textSize="17dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayout03"
android:layout_width="match_parent"
android:layout_height="#dimen/activity_list_height" >
<ImageView
android:id="#+id/ImageView03"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_margin="5dp"
android:src="#drawable/logo_d" />
<TextView
android:id="#+id/TextView03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/ImageView03"
android:text="TextView"
android:textColor="#color/black"
android:textSize="17dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayout02"
android:layout_width="match_parent"
android:layout_height="#dimen/activity_list_height" >
<ImageView
android:id="#+id/ImageView02"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_margin="5dp"
android:src="#drawable/logo_d" />
<TextView
android:id="#+id/TextView02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/ImageView02"
android:text="TextView"
android:textColor="#color/black"
android:textSize="17dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="#dimen/activity_list_height" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_margin="5dp"
android:src="#drawable/logo_d" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/imageView1"
android:text="TextView"
android:textColor="#color/black"
android:textSize="17dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayout01"
android:layout_width="match_parent"
android:layout_height="#dimen/activity_list_height">
<ImageView
android:id="#+id/ImageView01"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_margin="5dp"
android:src="#drawable/logo_d" />
<TextView
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/ImageView01"
android:text="TextView"
android:textColor="#color/black"
android:textSize="17dp" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:id="#+id/listItemInfo"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:background="#drawable/friend_cell_background2x"
android:clickable="true" >
<RelativeLayout
android:id="#+id/leftLayout"
android:layout_width="90dp"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imgCompany"
android:layout_width="60dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:scaleType="centerInside"
android:src="#drawable/user2x" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:scaleType="fitXY"
android:src="#drawable/online_indicator2s" />
</RelativeLayout>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/leftLayout"
android:background="#android:color/transparent"
android:gravity="left|center"
android:orientation="vertical"
android:paddingLeft="5dp" >
<TextView
android:id="#+id/lblCompanyName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Contact Name"
android:textColor="#color/white"
android:textSize="18dp"
android:textStyle="bold" >
</TextView>
<TextView
android:id="#+id/lblReawrdDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Last Played Offer"
android:textColor="#color/white"
android:textSize="17dp" >
</TextView>
</LinearLayout>
<ImageView
android:id="#+id/imageView4"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="5dp"
android:src="#drawable/facebook_btn2x" />
<Button
android:id="#+id/infoBtn"
style="?android:attr/buttonStyleSmall"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignRight="#+id/imageView4"
android:background="#drawable/info_btn2x"
android:clickable="true" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="13dp"
android:layout_toLeftOf="#+id/infoBtn"
android:text="Follows 30+"
android:textColor="#color/white"
android:textSize="11dp" />
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="75dp"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:layout_toLeftOf="#+id/textView2"
android:background="#drawable/fan_btn2x"
android:text="Fans 30+"
android:textColor="#color/white"
android:textSize="11dp" />
<ImageView
android:id="#+id/imageView5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageView4"
android:src="#drawable/google_btn2x" />
</RelativeLayout>
</RelativeLayout>
sorry for any layout problems that may make things difficult to read... but i hope this helps you guys to understand my problem... Thanks
UPDATE 2:
All of these answers have been helpful in some way, but i think the main issue that i must first fix is why the buttons do not receive click events until i have first scrolled away from that listItem, then back to it, then clicked the button again... If someone can help find a solution to THAT i think that everything else will be much easier to solve...
Thanks...
A screenshot as requested, but remember that this shot was taken on a samsung galaxy tab 10.1 and due to me using the same layout for this larger screen, it looks much different from what it does on the phone i usually test with (Motorola droid x that isnt rooted and cant take screenshots...)
Another Update:
I managed to get the clicking and animation working nicely by Extending ArrayAdapter instead of base adapter. Sadly i am still experiencing problems as only the bottom half of the list is clickable. The top half of the list still behaves as before with the very glitchy click events... Any ideas as to what is happening this time? Thanks...
Well this isn't really an answer, but after rewriting this a few times I managed to fix it so that it functions exactly the way I wanted.
This time I left all of the data separate from each view and had each list item be a custom class inheriting RelativeLayout and also implementing its own OnClickListener for its specific infoBtn.
My adapter now simply extends ArrayAdapter<> and overrides this getView() method:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView != null && (convertView instanceof FriendListItem2))
((FriendListItem2) convertView).setFriendInfo(friends.get(position));
else
convertView = new FriendListItem2(getContext(), friends.get(position));
return convertView;
}
Finally, in the main activity for this page I simply set the ListView with an adapter that I passed the data to.
This is all much cleaner than I had before and I wish it hadn't taken several rewrites of the code to get it right. Hopefully someone can benefit from this, though I still have no clue why I was getting a problem before.
Thanks for all previous suggestions.
try using this property in the top level layout in which your child views are placed.
android:descendantFocusability="blocksDescendants"
Its a bit tricky but I would suggest that if the above line does not work, try toggling between the removing of focusable=true and focusable="false" from the buttons. It should work.
Cheers!
That is a complex layout to create for every row...
Anyway, when you use the new keyword you are creating a different scope. In short your onClickListener does not see the 30 different extraListItemInfo references you expect it to see.
Try something like this:
#Override
public void onClick(View v) {
LinearLayout extraListItemInfo = v.getParent();
...
add android:onClick="onClick" to your button xml, it'll make it call the onClick() method
I had the same problem. Try taking the "android:clicable="true" " from the Relative Layout. When you do that the activity expects you to do make setOnClickListener to that RelativeLayout . It worked for me
you can fire click event on button from getView() method of ListViewAdapter Class.
See this question
Android : How to set onClick event for Button in List item of ListView.