This question already has answers here:
Error inflating custom view
(5 answers)
Closed 2 years ago.
I am trying to do a photo editor app for my own learning and I am struggling to incorporate a View subclass in an XML file to better design the process.
Here is the XML code :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".home">
<com.example.digitaldesign.createObjectLayout
android:id="#+id/CreateObj"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Here is the View Class:
package com.example.digitaldesign;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.View;
public class createObjectLayout extends View {
Bitmap tshirt;
public createObjectLayout(Context context) {
super(context);
setBackgroundResource(R.drawable.wall);
tshirt = BitmapFactory.decodeResource(getResources(),R.drawable.tshirt);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect trect = new Rect();
trect.set(50,50,1050,1350 );
canvas.drawBitmap(tshirt,null,trect,null);
}
}
And here is the Activity:
```package com.example.digitaldesign;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.LinearLayout;
public class createObject extends AppCompatActivity {
createObjectLayout CreateObj;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CreateObj = new createObjectLayout(this);
LinearLayout layout1 =(LinearLayout) findViewById(R.id.CreateObj);
layout1.addView(CreateObj);
setContentView(R.layout.createobjectlyt);
}
}
And the error:
Caused by: android.view.InflateException: Binary XML file line #10: Binary
XML file line #10: Error inflating class
com.example.digitaldesign.createObjectLayout
Caused by: android.view.InflateException: Binary XML file line #10:
Error inflating class com.example.digitaldesign.createObjectLayout
Caused by: java.lang.NoSuchMethodException: <init> [class
android.content.Context, interface android.util.AttributeSet]
I tried to do everything like here : https://stackoverflow.com/questions/16504243/add-a-button-to-view#= , but i still get the error. Can you please tell me what am i doing wrong and how to fix it?
First of all you must get an error as you try to inflate widgets from XML layout before using setContentView()
So, modify your code to transfer setContentView() just after super.onCreate(savedInstanceState);
public class createObject extends AppCompatActivity {
createObjectLayout CreateObj;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.createobjectlyt);
CreateObj = new createObjectLayout(this);
...
}
}
The second thing you need to include all the constructors of your custom view
public class createObjectLayout extends View {
Bitmap tshirt;
public createObjectLayout(Context context) {
super(context);
setBackgroundResource(R.drawable.ic_launcher_background);
tshirt = BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_gallery);
}
public createObjectLayout(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setBackgroundResource(R.drawable.ic_launcher_background);
tshirt = BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_gallery);
}
public createObjectLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setBackgroundResource(R.drawable.ic_launcher_background);
tshirt = BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_gallery);
}
public createObjectLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setBackgroundResource(R.drawable.ic_launcher_background);
tshirt = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect trect = new Rect();
trect.set(50, 50, 1050, 1350);
canvas.drawBitmap(tshirt, trect, trect, new Paint());
}
}
Third, you will get ClassCastException as you inflate your custom view as a LinearLayout so change it to
createObjectLayout myView = findViewById(R.id.CreateObj);
Also as your custom view is not a ViewGroup, then you can't add views to it. So the below statement will raise exception
layout1.addView(CreateObj);
I encourage your to have a look at Android Custom Views
Related
I've been trying to get an app idea of mine to come to fruition for some time now. The idea is a weather app in which users can choose the content they want to see, and it is represented by cards (CardViews). For example, if they want to see only current weather and a 3 day forecast, they can enable that, and they'll see only those two cards in the MainActivity in a Google Now sort of fashion.
I've run into a few problems, and I need some help.
Firstly, how can I create the CardViews dynamically? My first attempt had the views completely defined in XML, but that didn't work very well because it doesn't seem very intuitive to hide/show them all the time. So I decided to extend the CardView class into things like a CurrentWeatherCardView and create the card completely programatically.
Here's the class I created from that. It's a child of the WeatherCardView class, which just extends CardView and doesn't do a whole lot else at this point.
package com.photonfighterlabs.particleweather.weathercardviews;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.photonfighterlabs.particleweather.MainActivity;
import com.photonfighterlabs.particleweather.weatherobjects.CurrentWeather;
import com.photonfighterlabs.particleweather.weatherobjects.Weather;
import java.io.File;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
public class CurrentWeatherCardView extends WeatherCardView {
private ViewGroup viewGroup;
private LinearLayout linearLayout_600, linearLayout_604, linearLayout_434;
private TextView cw_title, temp_text_view;
private ImageView icon_image_view;
private int is_day;
private CurrentWeather currentWeather;
public CurrentWeatherCardView(CurrentWeather currentWeather, Context context, Activity activity, ViewGroup viewGroup) {
super(context, activity);
this.currentWeather = currentWeather;
this.currentWeather.initialize(context, activity, MainActivity.API_KEY);
this.context = currentWeather.getContext();
this.viewGroup = viewGroup;
this.currentWeather.doOnResponse(() -> {
setupLayout();
setCw_title(currentWeather.getName(), currentWeather.getText());
Weather.setIconDrawable(currentWeather.getIcon(), icon_image_view, currentWeather.getIs_day());
setTemperature(currentWeather.getTemp_f());
});
}
public CurrentWeatherCardView(Context context) {
super(context);
}
public CurrentWeatherCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CurrentWeatherCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void setupLayout() {
LayoutParams cardParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, pixels(200));
cardParams.setMargins(
pixels(15),
pixels(15),
pixels(15),
0
);
super.setLayoutParams(cardParams);
super.setRadius(pixels(4));
super.setUseCompatPadding(true);
linearLayout_604 = new LinearLayout(context);
linearLayout_604.setBaselineAligned(false);
linearLayout_604.setOrientation(VERTICAL);
LayoutParams layout_170 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
linearLayout_604.setLayoutParams(layout_170);
this.addView(linearLayout_604);
linearLayout_600 = new LinearLayout(context);
linearLayout_600.setOrientation(LinearLayout.HORIZONTAL);
LayoutParams layout_676 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, pixels(50));
linearLayout_600.setLayoutParams(layout_676);
linearLayout_604.addView(linearLayout_600);
cw_title = new TextView(context);
cw_title.setTypeface(Typeface.SANS_SERIF);
cw_title.setTextSize(pixels(5));
LayoutParams layout_914 = new LayoutParams(pixels(250), pixels(25));
layout_914.setMarginStart(pixels(10));
layout_914.topMargin = pixels(10);
cw_title.setLayoutParams(layout_914);
linearLayout_600.addView(cw_title);
icon_image_view = new ImageView(context);
LayoutParams layout_501 = new LayoutParams(pixels(75), pixels(40));
layout_501.setMarginStart(pixels(45));
layout_501.topMargin = pixels(10);
icon_image_view.setLayoutParams(layout_501);
linearLayout_600.addView(icon_image_view);
linearLayout_434 = new LinearLayout(context);
linearLayout_434.setOrientation(HORIZONTAL);
LayoutParams layout_204 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
linearLayout_434.setLayoutParams(layout_204);
temp_text_view = new TextView(context);
temp_text_view.setTextAlignment(TEXT_ALIGNMENT_TEXT_START);
temp_text_view.setTextSize(pixels(8));
LayoutParams layout_725 = new LayoutParams(pixels(100), pixels(100));
layout_725.setMarginStart(pixels(25));
layout_725.topMargin = pixels(10);
temp_text_view.setLayoutParams(layout_725);
linearLayout_434.addView(temp_text_view);
linearLayout_604.addView(linearLayout_434);
viewGroup.addView(this);
}
private void setCw_title(String title, String condition) {
cw_title.setText(title + " - " + condition);
}
private void setTemperature(double temp) {
temp_text_view.setText(String.valueOf((int) temp) + '\u00b0');
}
}
It's messy, but is there a better way? Doing it this way allows me to create this CardView by just instantiating the class, but I'm running into issues with figuring out what kind of view I should put these in. RecyclerView doesn't really seem like the right choice because as far as I can tell it's creates cards from a dataset. In my case, the CurrentWeatherCardView will always be the same.
That leads me to my next question. In what way can I have a scrollable, side-swipeable set of cards? RecyclerView? ListView? I'm pretty lost, and any guidance would help.
CardView is extended from FrameLayout, so you can just use a xml to design what your card looks like, and use findViewById in this CurrentWeatherCardView. For example:
public CurrentWeatherCardView(Context context) {
super(context);
init();
}
public CurrentWeatherCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CurrentWeatherCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
LayoutInflater.from(this).inflate(R.layout.xxx, this, true);
xxx = findViewById(R.id.xxxxx);
...
xxx.setText(xxxx)
// if you want to change visibility, just call:
setVisibility(View.GONE/View.VISIBILE);
}
This question already has answers here:
How to set a particular font for a button text in android?
(9 answers)
Closed 5 years ago.
I created an android studio default navgation view and i put two buttons in nav_header_main.xml (see the picture below)
now i want to set a custom font for the button.
i tried this in MainActivity.java :
Typeface font = Typeface.createFromAsset(getAssets(), "fonts/myfont.ttf");
Button b = (Button) findViewById(R.id.login_btn);
b.setTypeface(font);
but it didn't work!!
how can i do this?
Screenshot
You have to write a custom class extending from Button.
Here is an example:
package com.example.test;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.TextView;
public class CustomFontButton extends Button {
public CustomFontButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomFontButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomFontButton(Context context) {
super(context);
init();
}
private void init() {
Typeface font = Typeface.createFromAsset(getContext().getAssets(), "fonts/myfont.ttf");
setTypeface(font);
}
}
Use it from XML:
<com.example.test.CustomFontButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button Text" />
I need your help on this. I am going to make an app using ViewPager and I since I never been programming for android before I thought it would be good to make a sample app first. I want to use the ViewPager a little bit differently than the classic list-of-items-style so I made an app that will show all the colors (or every 10th color) from #000000 to #FFFFFF.
It doesn't work. I've started the app on the emulator but I just get a white screen. If the default position of the ViewPager when starting is 0 then the color should be black. And when I try to make a breakpoint the program doesn't stop, or it's never reaching the point. I'm using eclipse.
These are the files of the project
MainActivity.java
package com.example.colorswipe;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends Activity {
private ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager=(ViewPager)this.findViewById(R.id.pager);
mPager.setAdapter(new MyAdapter());
}
private class MyAdapter extends PagerAdapter {
#Override
public int getCount() {
return 0xFFFFFF/10;
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return false;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ColorView view=new ColorView(container.getContext());
view.setBackgroundColor(android.graphics.Color.parseColor(String.format("#%06X", position*10)));
view.setText(position);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
ColorView.java
package com.example.colorswipe;
import android.content.Context;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ColorView extends LinearLayout {
private TextView tv;
public ColorView(Context context) {
super(context);
LayoutParams params=new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.setLayoutParams(params);
TextView tv=new TextView(context);
this.tv=tv;
this.addView(tv);
}
public void setText(int position) {
tv.setText(Integer.toString(position).toCharArray(), 0, Integer.toString(position).length());
}
}
EDIT - the view pager is there , but I think you don't resolve the color correctly.
I found the problem. isViewFromObject must be implemented as return arg0==arg1.
OK, I have a settings activity that is filled from a preferences.xml with addPreferencesFromResource(R.xml.preferences);, there is a dialog preference:
<com.android.maxr1998.cleanit.DialogPreference
android:title="#string/pref_dev"
android:key="dev"
android:dialogIcon="#drawable/alerts_and_states_warning"
android:dialogLayout="#layout/dev_dialog"
android:positiveButtonText="#android:string/yes"
android:negativeButtonText="#android:string/cancel"/>
Now, when I click Yes, I want another Activity to be launched...
This is my DialogPreference.class
package com.android.maxr1998.cleanit;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Region;
import android.provider.ContactsContract;
import android.util.AttributeSet;
public class DialogPreference extends android.preference.DialogPreference {
public DialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DialogPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public interface ClickListener {
public void onPositiveBtnClicked(...?);
}
}
What do I specifically have to put at "...?" ?
Solved it this way:
Used normal preference
Applied onclicklistener on Preference in Activity
Launch AlertDialog from it
Positive button click in alertdialog fires up activity
Write a Interface for the DialogPreference. Implement that in your activity. In positive click event callback.
class DialogPreference extends ... {
public interface ClickListener {
public void onPositiveBtnClicked(...);
}
public void setListener(ClickListener l) {
mClickListener = l;
}
#Override
onClick(DialogInterface dialog, int which) {
if(which == DialogInterface .BUTTON_POSITIVE) {
mClickListener.onPositiveBtnClicked(...)
}
}
}
My problem is really straight forward. I can't seem to figure out why it's throwing an error of this kind (to add, I've never really used Java but have to for a simple android app now).
In my activity class I declare:
private MyWebView web;
Inside the 'onCreate' method I do this:
try {
web = (MyWebView)findViewById(R.id.webview);
}
catch(Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
}
The class 'MyWebView' looks like this:
import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;
public class MyWebView extends WebView {
public MyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
}
}
This throws an a 'ClassCastException' with detailMessage = "android.webkit.WebView.
I'd really appreciate some help.
Thanks
the name in the layout was the one thing which was wrong. After I tried it again it errored again, but this time it triggered a 'MethodNotFoundException'. It seems like you have to implement this constrcutor
MyWebView(Context context, AttributeSet attrs)
instead of this one
MyWebView(Context context, AttributeSet attrs, int defStyle)
like eclipse suggests...
you have to name your custom WebView like this in your layout:
<yourpackagename.MyWebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
yourpackagename: is the name of the package in wich you decalred your MyWebView Class