Customview is null with findViewById [duplicate] - android

I have an activity loaded from XML, with views having IDs as usual:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="110dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center_horizontal"
android:background="#drawable/white_circle">
<com.myapp.views.CircleImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-12dp"
android:background="#drawable/price_background">
<TextView
android:id="#+id/priceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:text="0.1 BTC"
android:textAllCaps="true"
android:textColor="#color/white"
android:textSize="10sp"
android:textStyle="bold" />
</FrameLayout>
<TextView
android:id="#+id/nameView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:gravity="center_horizontal"
android:lineSpacingMultiplier="0.8"
android:lines="2"
android:text="Bacon Cheeseburger"
android:textSize="10sp" />
</LinearLayout>
</FrameLayout>
I'm trying to reference three views in code:
public ItemViewHolder(View itemView) {
super(itemView);
nameView = itemView.findViewById(R.id.nameView);
priceView = itemView.findViewById(R.id.priceView);
imageView = itemView.findViewById(R.id.imageView);
}
nameView and priceView are referenced correctly, however, imageView isn't being referenced and is null:
Why can't I reference imageView?
(If I traverse the view tree, it is there.)
UPDATE: I did both Clean Project and Invalidate Caches/Restart, the problem persists.
UPDATE 2: ItemViewHolder is derived from RecyclerView.ViewHolder. CircleImageView is derived from FrameLayout (not ImageView). This XML is the layout of my view holder.
UPDATE 3: Here is my circle view's constructor:
public class CircleImageView extends FrameLayout {
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context);
init();
}
public CircleImageView(#NonNull Context context, #Nullable AttributeSet attrs, #AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
...
}
Also, as Subzero noted, I've checked the ID property (mID field) of the view, and it's -1, which seems to be the cause of the problem. I have no idea why it is -1 though.

Change the super call in your two-parameter constructor to:
super(context, attrs);
When a View is inflated from a layout, the XML attributes and their values are passed into the two-parameter constructor via the AttributeSet. If you don't pass that to the superclass, the id you've specified in the XML is never set on the View, so findViewById() won't find it with the given ID.

I like Use this as follows, hope it is helpful.
public class CircleImageView extends FrameLayout {
public CircleImageView(Context context) {
this(context,null);
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context.attrs,0);
}
public CircleImageView(#NonNull Context context, #Nullable AttributeSet attrs, #AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
...
}

I think the problem is, that your imageView in layout.xml is a custom view (com.myapp.views.CircleImageView), not a regular android ImageView.
Try cast to ImageView, if the class extends imageview
ImageView iv = (ImageView) itemView.findViewById(R.id.imageView));
or use it as your custom view
CircleImageView iv = (CircleImageView) itemView.findViewById(R.id.imageView));

Related

findViewById not working for specific view

I have an activity loaded from XML, with views having IDs as usual:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="110dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center_horizontal"
android:background="#drawable/white_circle">
<com.myapp.views.CircleImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-12dp"
android:background="#drawable/price_background">
<TextView
android:id="#+id/priceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:text="0.1 BTC"
android:textAllCaps="true"
android:textColor="#color/white"
android:textSize="10sp"
android:textStyle="bold" />
</FrameLayout>
<TextView
android:id="#+id/nameView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:gravity="center_horizontal"
android:lineSpacingMultiplier="0.8"
android:lines="2"
android:text="Bacon Cheeseburger"
android:textSize="10sp" />
</LinearLayout>
</FrameLayout>
I'm trying to reference three views in code:
public ItemViewHolder(View itemView) {
super(itemView);
nameView = itemView.findViewById(R.id.nameView);
priceView = itemView.findViewById(R.id.priceView);
imageView = itemView.findViewById(R.id.imageView);
}
nameView and priceView are referenced correctly, however, imageView isn't being referenced and is null:
Why can't I reference imageView?
(If I traverse the view tree, it is there.)
UPDATE: I did both Clean Project and Invalidate Caches/Restart, the problem persists.
UPDATE 2: ItemViewHolder is derived from RecyclerView.ViewHolder. CircleImageView is derived from FrameLayout (not ImageView). This XML is the layout of my view holder.
UPDATE 3: Here is my circle view's constructor:
public class CircleImageView extends FrameLayout {
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context);
init();
}
public CircleImageView(#NonNull Context context, #Nullable AttributeSet attrs, #AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
...
}
Also, as Subzero noted, I've checked the ID property (mID field) of the view, and it's -1, which seems to be the cause of the problem. I have no idea why it is -1 though.
Change the super call in your two-parameter constructor to:
super(context, attrs);
When a View is inflated from a layout, the XML attributes and their values are passed into the two-parameter constructor via the AttributeSet. If you don't pass that to the superclass, the id you've specified in the XML is never set on the View, so findViewById() won't find it with the given ID.
I like Use this as follows, hope it is helpful.
public class CircleImageView extends FrameLayout {
public CircleImageView(Context context) {
this(context,null);
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context.attrs,0);
}
public CircleImageView(#NonNull Context context, #Nullable AttributeSet attrs, #AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
...
}
I think the problem is, that your imageView in layout.xml is a custom view (com.myapp.views.CircleImageView), not a regular android ImageView.
Try cast to ImageView, if the class extends imageview
ImageView iv = (ImageView) itemView.findViewById(R.id.imageView));
or use it as your custom view
CircleImageView iv = (CircleImageView) itemView.findViewById(R.id.imageView));

How to make custom EditText [duplicate]

This question already has answers here:
Android EditText view Floating Hint in Material Design
(10 answers)
Closed 5 years ago.
I am trying to make custom EditText Something look like this.
Currently i am using Custom View Inheriting from ConstraintLayout
DefaultEditTextContainerView.java
public class DefaultEditTextContainerView extends ConstraintLayout
{
#BindView(R.id.titleText)
public TextView titleText;
#BindView(R.id.contentEditText)
public EditText contentEditText;
private String mTitleText;
private String mHintText;
public DefaultEditTextContainerView(Context context) {
super(context);
init(null, 0);
}
public DefaultEditTextContainerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public DefaultEditTextContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyle) {
View view = inflate(getContext(), R.layout.view_default_edit_text_container_view,
this);
ButterKnife.bind(this, view);
//region Load attributes
final TypedArray typedArray = getContext().obtainStyledAttributes(
attrs, R.styleable.DefaultEditTextContainerView, defStyle, 0);
if (typedArray.hasValue(R.styleable.DefaultEditTextContainerView_titleText)) {
mTitleText = typedArray.getString(
R.styleable.LandingPageSectionItemView_titleText);
}
if (typedArray.hasValue(R.styleable.DefaultEditTextContainerView_hintText)) {
mHintText = typedArray.getString(
R.styleable.DefaultEditTextContainerView_hintText);
}
typedArray.recycle();
// endregion
titleText.setText(mTitleText);
contentEditText.setHint(mHintText);
}
}
view_default_edit_text_container_view.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:maxHeight="100dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="24dp"
android:background="#color/colorLight"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout10"/>
<TextView
android:id="#+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="필드 이름"
android:textColor="#color/textLightDark"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/linearLayout10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/titleText">
<EditText
android:id="#+id/contentEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#android:color/transparent"
android:ems="10"
android:hint="예) 힌트 텍스트"
android:inputType="text"
android:padding="10dp"
android:singleLine="true"
android:textColor="#color/textLightDark"
android:textColorHint="#color/colorLight"
android:textSize="18sp"
tools:layout_editor_absoluteX="99dp"
tools:layout_editor_absoluteY="271dp"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
But the problem is, I have to access more than 5 attributes that are assigned to EditText. So i thought my CustomView Should Inherit from EditText. And that's what i am trying to do...
how can i inherit from EditText And create the same looking view as above?
OR
how can i Access all EditText Attributes from xml not specifing and overriding attributes via attr.xml ...
thank you!
===Edit==
what i want
ParentView(ConstraintLayout)
- ViewA(TextView)
- ViewB(EditText)
want to make a view looks like that but inherit from ViewB(EditText)
so i can mainly access to EditText's attributes
From your mockup which shows the desired result,you might like this library to achieve this easily:https://github.com/HITGIF/TextFieldBoxes.I have used this library before and it is pretty easy to implement.
Here is the preview of the output the library gives:

Remove Padding between drawableTop and text

I have CustomLayout which has TextView on which I am setting text and drawable programmatically however the problem is when I set the drawable it is adding a huge padding with what I want is drawable to be more at the center rather than at the top.
Custom ViewGroup
public class ProfileGridView extends FrameLayout {
public ProfileGridView(#NonNull Context context) {
super(context);
initView(context,null);
}
public ProfileGridView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
initView(context,attrs);
}
public ProfileGridView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context,attrs);
}
#TargetApi(21)
public ProfileGridView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(context,attrs);
}
public void initView(Context context, AttributeSet attrs) {
TextView gridTextView;
View view = inflate(context, R.layout.square_grid, null);
gridTextView = (TextView) view.findViewById(R.id.grid_description);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProfileGridView);
Drawable drawable = array.getDrawable(R.styleable.ProfileGridView_drawble);
String description = array.getString(R.styleable.ProfileGridView_grid_description);
gridTextView.setText(description);
gridTextView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
addView(view);
array.recycle();
}
}
CustomView LayoutFile
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
android:gravity="center"
android:padding="0dp"
android:textSize="20sp" />
MainActivit.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.views.ProfileGridView
android:layout_width="200dp"
android:layout_height="200dp"
app:drawble="#drawable/ic_message"
app:grid_description="Message"/>
</RelativeLayout>
Can you use a CustomView LayoutFile like this?
<?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="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="#+id/image"
android:layout_width="52dp"
android:layout_height="52dp" />
<TextView
android:id="#+id/grid_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:textSize="20sp"/>
</LinearLayout>
And set the drawable like this
ImageView image;
image = (ImageView) view.findViewById(R.id.image);
image.setImageDrawable(drawable);
Instead of
gridTextView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
EDIT
As you ask, you can make ProfileGridView wrap_content instead of 200dp. With setCompoundDrawablesWithIntrinsicBounds you attach the drawable to the bounds of the TextView (200dp). [You can check the documentation for more info](https://developer.android.com/reference/android/widget/TextView.html#setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable))
That's not a padding problem, is because you are setting the drawable width and height as 200dp
Can you use "wrap_content" in the drawable file?
If not just have a image file and set it as a drawable of the TextView
Setting the drawableBottom to an equally sized image will recenter the text. Here is a simple drawable that would do the trick:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="24dp"
android:height="24dp"/>
</shape>

Extendend LinearLayout - setOnClickListener don't works

I'm having some trouble when I extend a LinearLayout.
The onClick event is never fired.
My code:
public class Tab extends LinearLayout {
public Tab(Context context) {
super(context);
init(context);
}
public Tab(Context context, AttributeSet attrs) {
super(context, attrs);
// ... get attrs ...
init(context);
}
public Tab(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
inflate(context, R.layout.tab, this);
// ... some layout tasks ...
iconView.requestLayout();
}
}
Layout tab.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal|center_vertical"
android:background="#drawable/bg_tab"
android:clickable="true"
android:duplicateParentState="true">
<ImageView
android:id="#+id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_gravity="center_horizontal|center_vertical"
android:clickable="false"
android:duplicateParentState="true"/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal|center_vertical"
android:textAllCaps="true"
android:textColor="#drawable/tab_text_color"
android:textSize="11sp"
android:duplicateParentState="true"/>
</LinearLayout>
If I put a eventListener on a Tab's child view, it works, but when attached to the Tab itself is doesn't.
Can someone see where my mistake is?
I just set android:clickable to false on rootView and works! =)

Layout not being inflated in android custom component

I'm getting a null pointer exception in my custom view (which is derived from a LinearLayout) because it can't find its child views. Here is the code:
public class MyView extends LinearLayout
{
public MyView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
private TextView mText;
#Override
protected void onFinishInflate()
{
super.onFinishInflate();
mText = (TextView) findViewById(R.id.text);
if (isInEditMode())
{
mText.setText("Some example text.");
}
}
}
Here is the layout (my_view.xml):
<?xml version="1.0" encoding="utf-8"?>
<com.example.views.MyView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</com.example.views.MyView>
And here is how I put it in the XML file:
<com.example.views.MyView
android:id="#+id/my_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
But when I try to preview it in the layout editor I get an NPE on mText.setText(...) because getViewById() returns null.
What's going on?
Clarification
The reason I expect this to work, is if I do
MyView v = (MyView)inflater.inflate(R.layout.my_view);
((TextView)v.findViewById(R.id.text)).setText("Foo");
everything works fine. Is that not what the layout inflater does when it goes through a layout file? In any case, how can I handle both situations correctly (without getting pointless nested views)?
In you XML file you are trying to use a custom view class (com.example.views.MyView) and in the same time trying to add a TextView inside. It's not possible.
Here is what you need to change:
You must inflate XML file in the code:
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
LayoutInflater.from(context).inflate(R.layout.<your_layout>.xml, this);
}
And modify the XML layout file like this:
<?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" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</LinearLayout>

Categories

Resources