This is my source of testing Custom Layout (shows image and label).
XML CODE
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/screen_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#3535ff"
android:orientation="vertical"
android:padding="1dp" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:padding="20dp" >
<ImageView
android:id="#+id/screen_image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="#000000"
android:scaleType="centerInside"
android:src="#drawable/cam_1_20130117_105601_118" />
<TextView
android:id="#+id/screen_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/screen_image"
android:layout_centerHorizontal="true"
android:layout_marginBottom="3dp"
android:background="#95000000"
android:gravity="center_vertical|center_horizontal"
android:text="사출성형기 1호기"
android:textColor="#ffffff" />
</RelativeLayout>
</LinearLayout>
JAVA CODE
package com.example.testlayout;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.testscreen.R;
public class CustomScreen extends LinearLayout {
LinearLayout mLayout = null;
TextView mLabel = null;
ImageView mImage = null;
public CustomScreen(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomScreen(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomScreen(Context context) {
super(context);
init();
}
void init() {
LayoutInflater inflater = (LayoutInflater)getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.screen, this, true);
// mLabel = (TextView)findViewById(R.id.screen_label);
// mImage = (ImageView)findViewById(R.id.screen_image);
if (isInEditMode()) {
return;
}
}
}
With this code, I checked on Nexus One. It displays well.
The problem is on editor mode. Exactly on xml editer with preview.
When I add this view, error message appeared.
The following classes could not be instantiated :
- com.example.testlayout.CustomScreen (Open Class, Show Error Log) See the Error Log (Window > Show View) for more details. Tip: Use
View.isInEditMode() in your custom views to skip code when shown in
Eclipse
I want to check it on edit mode.
How can I check well like other views?
you have to add (!isInEditMode()) in each constructor. which tells if it not in edit Mode then initialized the stuff
if(!isInEditMode())
init(context);
and for initializing stuff follow this
also have a look at this
Related
This is my view's XML file:
<LinearLayout 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"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/bsv_edit_beaconname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="textPersonName"
android:text="Beacon Name" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/bsv_check_fix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/cinit_table_isfixpoint" />
<CheckBox
android:id="#+id/bsv_check_draw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/cinit_table_drawbeacon" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="#+id/bsv_btn_setpos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="set_position_click"
android:text="#string/cinit_set_position" />
<TextView
android:id="#+id/bsv_text_pos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Position ?" />
</LinearLayout>
With the corresponding java class being the following
package talogs.beacontalogs;
import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class BeaconSetupView extends LinearLayout {
private static final String TAG = "BeaconSetupView";
private EditText edit_beaconName;
private CheckBox check_isFixpoint;
private CheckBox check_draw;
private Button btn_setpos;
private TextView text_pos;
public BeaconSetupView(Context context) {
this(context, null);
}
public BeaconSetupView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public BeaconSetupView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
// inflate(getContext(), R.layout.beacon_setup_view, this);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate( R.layout.beacon_setup_view, this );
edit_beaconName = (EditText) findViewById(R.id.bsv_edit_beaconname);
check_isFixpoint = (CheckBox) findViewById(R.id.bsv_check_fix);
check_draw = (CheckBox) findViewById(R.id.bsv_check_draw);
btn_setpos = (Button) findViewById(R.id.bsv_btn_setpos);
text_pos = (TextView) findViewById(R.id.bsv_text_pos);
}
public void setPosition(Point point) {
Log.v(TAG, "setting position to " + point.toString());
text_pos.setText(String.format("(%d, %d)", point.x, point.y));
}
}
My custom view BeaconSetupView is created programmatically using this code when a button in an activity is pressed.
public void btn_addbeacon_Click(View view) {
BeaconSetupView beacon = new BeaconSetupView(this);
beaconList.addView(beacon, beaconList.getChildCount() - 1);
}
The button that's part of the custom view calls this method:
public void set_position_click(View view) {
ViewParent parent1 = view.getParent();
ViewParent parent2 = parent1.getParent();
BeaconSetupView bsv = (BeaconSetupView) view.getParent().getParent();
Log.v(LOG_TAG, "set_position called, point is currently " + String.valueOf(lastClicked));
if (lastClicked != null) {
bsv.setPosition(lastClicked);
}
}
The problem is that the button click cannot be implemented outside of the root activity (because it has data that I need), but I also need to get its corresponding BeaconSetupView. Calling view.getParent().getParent() and casting it results in a ClassCastException. So I tried changing the root element of the XML layout to BeaconSetupView, but that causes the app to crash when the view is first added to the activity.
I either need a way to cast my custom class properly and still be able to add it programmatically to my activity, or I need to be able to access the activity's instance from another class that doesn't have a reference to it. What are my options?
Is it possible to set an Icon in ActionBar "Text" using FontAwesome?
I have tried this way...
My menu item like that..
<item
android:id="#+id/action_chat"
android:orderInCategory="100"
android:title="#string/action_chat"
app:showAsAction="always"
android:actionLayout="#layout/chat_menu_icon"/>
My 'chat_menu_icon.xml'
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.bitmakers.techmonster.textview.FontAusomeTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="web"
android:id="#+id/test"
android:gravity="center|bottom"
android:text="#string/action_chat"
android:textSize="24sp"
android:textStyle="bold" />
</LinearLayout>
My Custom Font Class
package com.bitmakers.techmonster.textview;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class FontAusomeTextView extends TextView {
public static Typeface m_typeFace = null;
public FontAusomeTextView(Context context) {
super(context);
// TODO Auto-generated constructor stub
if (isInEditMode()) {
return;
}
loadTypeFace(context);
}
public FontAusomeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (isInEditMode()) {
return;
}
loadTypeFace(context);
}
public FontAusomeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) {
return;
}
loadTypeFace(context);
}
private void loadTypeFace(Context context) {
if (m_typeFace == null)
m_typeFace = Typeface.createFromAsset(context.getAssets(),
"fonts/fontawesome-webfont.ttf");
this.setTypeface(m_typeFace);
}
}
It is working when i using it in normal textview
You can use a nice library called android-iconify to achieve your goal.
Here is how you implement it on Toolbar/Actionbar items:
your_menu_layout.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
<item
android:id="#+id/item_settings"
showAsAction="ifRoom"
android:title="#string/title"/>
</menu>
Inside your onCreateOptionsMenu method:
menu.findItem(R.id.item_settings).setIcon(
new IconDrawable(this, FontAwesomeIcons.fa_cog)
.colorRes(R.color.your_color)
.actionBarSize());
And you are good to go :)
Use Custom ActionBar
create your own layout and include that in xml using
<include.../>
I'm trying to create a digital clock widget with custom typeface font.
I got clues from here
Solution was by extending TextView and put new attribute for custom font typeface. This is a good solution compared to drawing Canvas and Bitmap solution then pass it to RemoteViews.
I followed every step,
1. create custom class CustomFont.java
2. define style in attrs.xml
3. then put it in main.xml
but I got the following errors
WARN/AppWidgetHostView(18681): updateAppWidget couldn't find any view, using error view
WARN/AppWidgetHostView(18681): android.view.InflateException: Binary XML file line #17: Error inflating class upper.duper.widget.circular.clock.CustomFont
...
...
...
WARN/AppWidgetHostView(18681): Caused by: java.lang.ClassNotFoundException: upper.duper.widget.circular.clock.CustomFont in loader dalvik.system.PathClassLoader
Something missing?
Here I attach the codes
This is CustomFont.java
package upper.duper.widget.circular.clock;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
public class CustomFont extends TextView {
private static final String TAG = "CustomFont";
public CustomFont(Context context) {
super(context);
}
public CustomFont(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public CustomFont(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.CustomFont);
String customFont = a.getString(R.styleable.CustomFont_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface tf = null;
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface: "+e.getMessage());
return false;
}
setTypeface(tf);
return true;
}
}
And this is my main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:updup="http://schemas.android.com/apk/res/upper.duper.widget.circular.clock"
android:background="#00000000"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<AnalogClock android:id="#+id/AnalogClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:dial="#drawable/widgetdial_white"
android:hand_hour="#drawable/widgethour"
android:hand_minute="#drawable/widgetminute"/>
<upper.duper.widget.circular.clock.CustomFont
android:id="#+id/TIME"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textStyle="bold"
android:layout_gravity="center"
android:singleLine="true"
android:ellipsize="none"
android:textSize="12sp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="2dp"
updup:customFont="ALPNMAIN.TTF" />
And I put my custom font (ALPNMAIN.TTF) on assets folder already.
This is attrs.xml
<resources>
<declare-styleable name="CustomFont">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
Now I feel this is not possible to have something "custom" for app widget.
Look here
upper.duper.widget.circular.clock.CustomFont
You appear to be attempting to use a custom class in a layout for an app widget. This is not supported.
I have been searching for the past few hours to the answer to a very dumb question. I know how to draw on the canvas in android if you extend the view class, modify onDraw and set setContentView() to a new instance of that class. However, I need to also have 2 TextViews and 2 EditTexts at the bottom of the activity and if setContentView() is set to only have that view, these views will, obviously, not display. How can put all of these on the screen?
EDIT: Here is my code: (the package name is android.physicsengine)
package android.physicsengine;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class ResultantForceEngine extends Activity {
private EditText mag;
private EditText dir;
private View image;
private RelativeLayout layout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.resultant_force);
mag = (EditText)findViewById(R.id.magnitude);
dir = (EditText)findViewById(R.id.direction);
}
public class MyView extends View{
public MyView(Context context){
super(context);
}
public MyView(Context context, AttributeSet attrs){
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(Color.RED);
canvas.drawLine(canvas.getWidth()/2, canvas.getHeight()/2-200, canvas.getWidth()/2 ,canvas.getHeight()/2+200, circlePaint);
canvas.drawLine(canvas.getWidth()/2-200, canvas.getHeight()/2, canvas.getWidth()/2+200 ,canvas.getHeight()/2, circlePaint);
}
}
}
and the xml
<view class="android.physicsengine.ResultantForceEngine$MyView"
android:id="#+id/image"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<TextView android:id="#+id/magText"
android:text="Magnitude (N) ="
android:textSize="15dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:gravity="center_vertical"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true" />
<EditText android:id="#+id/magnitude"
android:inputType="numberDecimal"
android:layout_alignParentBottom="true"
android:layout_toRightOf ="#id/magText"
android:layout_width="wrap_content"
android:padding="3dip"
android:layout_height="wrap_content" />
<TextView android:id="#+id/dirText"
android:text="Angle (deg) ="
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dip"
android:layout_alignParentBottom="true"
android:layout_toRightOf ="#id/magnitude"
android:padding="3dip"
android:gravity="center_vertical" />
<EditText android:id="#+id/direction"
android:inputType="numberDecimal"
android:layout_alignParentBottom="true"
android:layout_toRightOf ="#id/dirText"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"
android:padding="3dip"
android:layout_width="wrap_content"/>
Basically you need to define your XML file with your custom view class and the other widgets you have. In your case, there would be the custom view, 2 textviews and 2 edittexts in the XML file.
You define the custom view in XML just like any other widget, except you use the namespace of the view and the class name.
<com.example.android.myCustomView
android:id="#+id/my_custom_view"
...
Then inside your activity a simple call
setContentView(R.layout.main);
Edit: The problem is your class is private, so it "isn't seen" when your activity makes a call the layout and tries to inflate it.
Edit2: Of course this won't work, you're using an inner class! You have to communicate stuff like this if you expect to get answers.
The XML syntax for an inner class is different.
<view class="com.example.android.MyClass$MyInnerClass"
You should be able to use the class that you extended in your res/layout/main.xml just like you would any other View class, and add your TextView and EditTexts in the layout .xml file like normal. I have not personally done this, but I have used custom View classes in this way.
Then for your setContentView you would just use the layout .xml file like:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
How do I pass the current AttributeSet to a custom View class? If I use a constructor that only has Context in the arguments, I lose all themes and the ability to use "style" tags in the xml for that custom View.
What I've done is create an activity that contains my custom view already in the xml file, and then programmatically create a new one and add it to the layout. What I find is the one that is made in the xml has the proper styling, and the one I create programmatically doesn't.
The difference between the two as far as I can tell is that the system uses the CustomLayout1(Context context, AttributeSet attrs) constructor. The problem is I can't figure out how to get the AttributeSet for the application to pass to this custom view when I create it programmatically.
Here's the Activity:
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class ThemeOne extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout layout = (LinearLayout) findViewById(R.id.mainlayout);
layout.addView(new CustomLayout1(getApplicationContext()));
}
}
Here's the main xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.clearsync.test.theme1.CustomLayout1 android:id="#+id/maincustom"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
The custom view class:
import com.clearsync.test.theme1.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
public class CustomLayout1 extends LinearLayout {
private Context context = null;
public CustomLayout1(Context context) {
super(context);
this.context = context;
create();
}
public CustomLayout1(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
create();
}
private void create(){
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.inflateme, this, true);
}
}
and finally, the custom view xml:
<?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">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Oh, Hewroh..."
style="?textview_style1" />
</LinearLayout>
Instead of building it with layout.addView(new CustomLayout1(getApplicationContext())); inflate it with the LayoutInflater in your Activity.
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.yourcustomviewxml, layout);
Your code creates LinearLayout inside of linear layout for your custom view. Correct way of doing this is changing your custom view xml from:
<?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">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Oh, Hewroh..."
style="?textview_style1" />
</LinearLayout>
to
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Oh, Hewroh..."
style="?textview_style1"
/>
</merge>
What are you trying to accomplish here? Looks like you have an endless recursive loop here using your create method, as inflate() will call the constructor that takes attributes. Anyways to answer your question you get the attributes in the constructor with the attributes!
That is the constructor that is called when loading from XML, otherwise it calls one of the other constructors that you supply.
One other helpful thing, you can get a reference to the inflater much easier from the static View method. View.inflate :D