I know this has been asked many times on SO, but somehow I don't get to the solution reading the existing answers.
The most simple thing, I want to add a custom view in an activity.
The custom view MyView has a background color, as well as its subView.
But the activity is just plain white and does not seem to display the custom view.
Why is that?
MainAcivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
MyView myView = findViewById(R.id.myView);
}
}
main_activity.xml:
<?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="match_parent"
tools:context=".MainActivity">
<com.myapp.MyView
android:id="#+id/myView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
MyView.java
public class MyView extends LinearLayout {
public MyView(Context context) {
super(context);
init(context);
}
public MyView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
inflate(context, R.layout.my_view, this);
subView = findViewById(R.id.subView);
//...
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
my_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff00ff"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="#+id/subView"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="#ff00ff"
tools:ignore="ContentDescription" />
</LinearLayout>
If you don't skip onLayout implementation in you snippet then you remove layout logic of your custom view, just don't override it:
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
Related
I have an item which has apple, pear and lemon. I made separate layouts for apples, pears and lemons.
I want to get the layout of that element if any element is selected. I tried that put the correct layout to viewStub according to selected layout with inflate() function. But the performance of defining layouts with inflate() each time was exhausting and sometimes caused incorrect work.
Please help me.
My general view codes:
public class MyView extends RelativeLayout {
private ViewStub viewStub;
private int lemon = 1, apple = 2, pear = 3;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
this.viewStub = ViewUtil.findById(this, R.id.view_stub);
}
public void bindElements(int type){
if (type == lemon) {castLemon(); return;}
if (type == apple ) {castApple(); return;}
if (type == pear) {castPear(); return;}
public void castLemon() {
viewStub.setLayoutResource(R.layout.lemon_item);
LemonView lemonView = (LemonView) viewStub.inflate();
}
}
public void castApple() {
viewStub.setLayoutResource(R.layout.apple_item);
AppleView appleView = (AppleView) viewStub.inflate();
}
}
public void castPear() {
viewStub.setLayoutResource(R.layout.pear_item);
PearView pearView = (PearView) viewStub.inflate();
}
}
}
My general view xml:
<com.android.android.MyView
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/myView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout android:id="#+id/bodyLinear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ViewStub
android:id="#+id/view_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:gravity="start|center_vertical"
android:paddingBottom="5dp"/>
</LinearLayout>
</com.android.android.MyView>
LemonView.java:
public class LemonView extends FrameLayout {
private ImageView imageView;
public LemonView(Context context) {
this(context, null);
}
public LemonView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LemonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.lemon_view, this);
imageView = findViewById(R.id.image);
}
lemon_view:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.android.android.LemonView">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="#null"
android:gravity="center"
android:scaleType="centerCrop"/>
</merge>
lemon_item xml:
<?xml version="1.0" encoding="utf-8"?>
<com.android.android.LemonView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lemon_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Create all the layouts at once, then just show / hide the needed layout variant with .setVisibility(View.VISIBLE) / .setVisibility(View.GONE).
I have a created custom layout but it is not working. When I use include the layout instead of set com.samsung.android.app.spage.CustomView.WeatherStateView it is working ok. I found some answers like use the <merge> tag but it not working too, please help me:
weather_state_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/weather_state_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/current_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="current location" />
<include layout="#layout/detail_info_frag_hourly_content" /></LinearLayout>
WeatherStateView.java
public class WeatherStateView extends LinearLayout implements View.OnClickListener{
private static final String TAG = "WeatherStateView";
private TextView mCurrentLocation;
private Context mContext;
public WeatherStateView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WeatherStateView(Context context) {
super(context);
}
public WeatherStateView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context) {
mContext = context;
LayoutInflater.from(context).inflate(R.layout.weather_state_layout, this);
mCurrentLocation = (TextView) findViewById(R.id.current_location);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(w, h);
setMeasuredDimension(size, size);
}
}
in main_layout.xml
<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="match_parent"
tools:context=".WeatherModule.WeatherViewStateFragment">
<CustomView.WeatherStateView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/weather_state_main_layout"
android:orientation="vertical"
/>
You can use something like that
Simply give the cast to the view of included layout and then get it.
View test1View = findViewById(R.id.yourincludedlayoutid);
TextView t1 = (TextView) test1View.findViewById(R.id.emiscode);
Problem here is
LayoutInflater.from(context).inflate(R.layout.weather_state_layout, this);
Should change to ;
ViewGroup viewGroup = (ViewGroup) inflate(mContext , R.layout.weather_state_layout, null); addView(viewGroup);
Say I have this class MyView:
public class MyView extends GLSurfaceView {
private MyRenderer mRenderer;
public MyView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
init(ctx);
}
private void init(Context ctx) {
mRenderer = new MyRenderer(ctx);
setRenderer(mRenderer);
}
#Override
public void setBackground(Drawable background) {
mRenderer.setBackground(background);
}
}
That is inflated by MyActivity like this:
public class MyActivity extends Activity {
private MyView mView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
protected void init() {
setContentView(R.layout.my_layout);
mView = (MyView) findViewById(R.id.my_view);
}
}
To my knowledge setBackground is called by the inflater in setContentView, before init is called in MyView, so mRenderer has not been initialized yet.
It seems like a catch 22, because the view's attributes can't be set without the view's initialization, which happens after the attributes are set.
This is the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/background" >
<com.developer.app.MyView
android:id="#+id/my_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/background"
/>
<TextView
android:id="#+id/left_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="#drawable/left_arrow"
/>
<TextView
android:id="#+id/right_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="#drawable/right_arrow"
/>
<TextView
android:id="#+id/home_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:background="#drawable/home"
/>
</RelativeLayout>
You are right. setBackground() is called from View's constructor if android:background attribute was parsed. In your case it called here:
super(ctx, attrs);
If you want to set background to mRenderer, you can do it in init:
private void init(Context ctx) {
mRenderer = new MyRenderer(ctx);
setRenderer(mRenderer);
final Drawable background = getBackground();
if (background != null) {
mRenderer.setBackground(background);
}
}
and add a null-check in setBackground, because this method can be called from superclass' constructor before you set some value to mRenderer
#Override
public void setBackground(Drawable background) {
if (mRenderer != null) {
mRenderer.setBackground(background);
}
}
What i understood from your question. You need attributes of views in oncreate(). But unable to do so. the reason is at that point UI is not initialized yet. there is work around.
this link might help.
getWidth() and getHeight() of View returns 0
You have initialize its three functions for example and xml and java is as you are doing it.
public class MyEditText extends EditText {
public MyEditText(Context context) {
super(context);
this.setTextColor(Color.parseColor("#4789da"));
this.setBackgroundResource(R.drawable.edittext_back);
this.setTextSize(18);
this.setPadding(5,5,5,5);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.setTextColor(Color.parseColor("#4789da"));
this.setBackgroundResource(R.drawable.edittext_back);
this.setTextSize(18);
this.setPadding(5,5,5,5);
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setTextColor(Color.parseColor("#4789da"));
this.setBackgroundResource(R.drawable.edittext_back);
this.setTextSize(18);
this.setPadding(5,5,5,5);
}
}
i tried to create custom linear layout that have dynamic height and width = height. The custom layout is fine, but the child view not showing at my custom linear layout. i tried some way to fix it, but still cant solve it.
public class CustomLinearLayout extends LinearLayout {
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(height, height);
}
}
this is the xml that contain my custom linear layout. the child view not showing.
<com.example.admin.antriclient.CustomLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:autofit="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/bg_nomor_antrian"
android:padding="10dp"
>
<me.grantland.widget.AutofitTextView
android:id="#+id/service_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Teller"
android:textColor="#color/white"
android:textStyle="bold"
android:gravity="center_horizontal"
android:singleLine="false"
autofit:minTextSize="12sp"
/>
<me.grantland.widget.AutofitTextView
android:id="#+id/nomor_antrian"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="T21"
android:textSize="50sp"
android:textColor="#color/white"
android:textStyle="bold"
android:gravity="center_horizontal"
android:singleLine="true"
autofit:minTextSize="12sp"
/>
</com.example.admin.antriclient.CustomLinearLayout>
thanks in advance
My problem is because i didnt call the super.onMeasure() method. Thanks to Mike M.
my class should be like this
public class CustomLinearLayout extends LinearLayout {
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec,heightMeasureSpec);
//int height = MeasureSpec.getSize(heightMeasureSpec);
//setMeasuredDimension(height, height);
}
}
For me I had to add a LayoutInflater for it to show
public class SidebarLayout extends LinearLayout {
private static final String TAG = "SidebarLayout";
public SidebarLayout(Context context) {
super(context);
}
public SidebarLayout(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.sidebar, this);
}
public SidebarLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
<com.example.a3danimationtester.SidebarLayout
android:id="#+id/layout_sidebar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/layout_topbar" />
New to Android development, and I'm having trouble doing a simple drawing to a view using a canvas.
From what I've understood, something like this:
import android.content.Context;
import android.graphics.Canvas;
import android.view.View;
public class DrawView extends View
{
public DrawView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawRGB(255,0,0);
}
}
With this as my Activity:
public class Prototype1 extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
And this for the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.dhs2.prototype1.DrawView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
Should just draw red everywhere, but instead I just get a blank screen.
Any idea where I'm going wrong?
Since you added your custom view in an XML layout file, you should add 2 more constructors:
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
This is because you pass some attributes to the view, like fill_parent, wrap_content, so the constructor public DrawView(Context context) won't be called.
This would work however, if you won't declare your custom view in the XML layout file, but setting it directly from the onCreate() like this:
setContentView(new DrawView(this));