I'm trying to add a text element to a view that's been created. I've found some answers online, but haven't been able to tailor them. I'm using the TouchPaint example code. Every-time I run the app with the text element, the app fails. Would appreciate some help.
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create and attach the view that is responsible for painting.
mView = new MyView(this);
setContentView(mView);
mView.requestFocus();
TextView tvX= (TextView)findViewById(R.id.pointSize);
tvX.setText("TestText");
// Restore the fading option if we are being thawed from a
// previously saved state. Note that we are not currently remembering
// the contents of the bitmap.
mFading = savedInstanceState != null ? savedInstanceState.getBoolean("fading", true) : true;
}
View class
public class MyView extends View {
private static final int FADE_ALPHA = 0x06;
private static final int MAX_FADE_STEPS = 256/FADE_ALPHA + 4;
private Bitmap mBitmap;k
private Canvas mCanvas;
private final Rect mRect = new Rect();
private final Paint mPaint;
private final Paint mFadePaint;
private boolean mCurDown;
private int mCurX;
private int mCurY;
private float mCurPressure;
private float mCurSize;
private int mCurWidth;
private int mFadeSteps = MAX_FADE_STEPS;
public MyView(Context c) {
super(c);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setARGB(255, 255, 255, 255);
mFadePaint = new Paint();
mFadePaint.setDither(true);
mFadePaint.setARGB(FADE_ALPHA, 0, 0, 0);
}
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="${packageName}.${activityClass}" >
<TextView
android:id="#+id/pointSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
android:textColor="#FF0000"
android:visibility="visible" />
</RelativeLayout>
Try this:
LinearLayout lv = new LinearLayout(this);
tvX.setText("TestText");
lv .addView(tvX);
setContentView(lv);
Related
I am using a custom edittext but the problem is that I am unable to set a text for my custom edittext. Here is what all I tried from the available answers on SO,
setText not working for a Custom Edittext
This did not work still. I did not get any error,so no clued why it did not work.
Custom TextView - setText() called before constructor
This also did not work.
XML FILE
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#FFFFFF"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<com.random.practiceproject.LinedEditText
android:layout_width="301dp"
android:inputType="text"
android:layout_height="match_parent" />
</LinearLayout>
MainActivity
LinedEditText lt;
EditText et; //Normal edittext works
String s = "This is a sample string";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lt = new LinedEditText(this);
et = (EditText) findViewById(R.id.newt);
lt.setCursorVisible(true);
lt.setTextColor(Color.BLACK);
lt.setText(s,TextView.BufferType.EDITABLE);
et.setText(s, TextView.BufferType.EDITABLE);
}
Here is the code,
public class LinedEditText extends EditText {
private static Paint linePaint;
static {
linePaint = new Paint();
linePaint.setColor(Color.BLACK);
linePaint.setStyle(Paint.Style.STROKE);
}
public LinedEditText(Context context)
{
super(context);
}
public LinedEditText(Context context, AttributeSet attributes) {
super(context, attributes);
}
#Override
protected void onDraw(Canvas canvas) {
Rect bounds = new Rect();
int firstLineY = getLineBounds(0, bounds);
/*int firstLineY=0;
for(int i =0;i<getLineCount();i++)
{
firstLineY = (i + 1) * getLineHeight();
}*/
int lineHeight = getLineHeight();
int totalLines = Math.max(getLineCount(), getHeight() / lineHeight);
for (int i = 0; i < totalLines; i++) {
int lineY = firstLineY + i * lineHeight;
canvas.drawLine(bounds.left, lineY, bounds.right, lineY, linePaint);
}
super.onDraw(canvas);
}
}
The problem is that you create new instance of LineEditText in onCreate and working with it, but not adding to layout. In the layout there is another instance of LineEditText, that you don't use.
So you must either replace:
lt = new LinedEditText(this);
with:
lt = (LinedEditText) findViewById(/*provide your id*/)
or you need to add lt to layout through ViewGroup.addView(), but I think you need to use first variant.
I have a custom view class
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0x00660000;
...
public void printPoint(Point p, Boolean b){
if(p != null){
Paint testePaint = new Paint();
testePaint.setColor(0xFF0000FF);
testePaint.setAntiAlias(true);
testePaint.setStrokeWidth(brushSize);
testePaint.setStyle(Paint.Style.STROKE);
testePaint.setStrokeJoin(Paint.Join.ROUND);
testePaint.setStrokeCap(Paint.Cap.ROUND);
if(b){
testePaint.setColor(0xFFFF0000);
}else{
testePaint.setColor(0xFF0000FF);
}
drawCanvas.drawPoint(p.x, p.y, testePaint);
}
}
public void printPath(){
if(paths.size() > 0){
Path testePath = new Path();
Paint testePaint = new Paint();
testePaint.setColor(0xFF00FF00);
testePaint.setAntiAlias(true);
testePaint.setStrokeWidth(brushSize);
testePaint.setStyle(Paint.Style.STROKE);
testePaint.setStrokeJoin(Paint.Join.ROUND);
testePaint.setStrokeCap(Paint.Cap.ROUND);
testePath = paths.remove(0);
drawCanvas.drawPath(testePath, testePaint);
}
}
}
add the view to the layout and load it into MainActivity using
public class MainActivity extends Activity implements OnClickListener {
//TCP COM
private TcpClient mTcpClient;
//
private DrawingView drawView;
private ImageButton currPaint, drawBtn, eraseBtn, newBtn;
private float smallBrush, mediumBrush, largeBrush;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
drawView = (DrawingView)findViewById(R.id.drawing);
drawView.setBrushSize(mediumBrush);
....
}
when I click a button I call the following function
public void updateView(Linha l){
Log.d("TCP","updateView()");
if(l.getEscreve() == true){
drawView.printPath();
}
drawView.printPoint(l.getPonto(),l.getEscreve());
}
and it works but when I call it from onProgressUpdate from an asynctask I can only see the draws on the view if I click again on the button.
hmm I don't think you should be updating UI on a different thread. Instead you override onDraw in your custom view, and from your asynctask do postInvalidate to trigger onDraw being called on UI thread.
Add invalidate(); after drawPath and drawPoint resolved the problem :)
If I want to add a button in this class so that I can call the onclicklistener, how should I do it?
public class GameView extends View {
Path circle;
Paint cPaint;
Paint tPaint;
String z;
int i = 65, strt, arc, leftx, topy, rightx, bottomy, maxx, maxy;
boolean flag1, flag2, flag3;
double n1, n2;
int n, n3 = 180,n4,n5 = 90;
float f1 = 180, f2 = 90;
Button b1;
Random r = new Random();
RectF oval;
public GameView(Context context) {
super(context);
leftx = 0;
topy = 60;
rightx = 150;
bottomy = 120;
z = String.valueOf(Character.toChars(i));
cPaint = new Paint();
cPaint.setColor(Color.RED);
strt = 45;
arc = 315;
n1 = Math.random() * 600;
Log.d("random", z);
if (flag2 == false)
new DrawThread(this);
// cPaint.setStrokeWidth(2);
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setColor(Color.BLACK);
float scale = getResources().getDisplayMetrics().scaledDensity;
tPaint.setTextSize(20 * scale);
}
public void onSizeChanged(int w,int h,int oldh,int oldw) {
maxx = oldw;
maxy = oldh;
}
//#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
oval = new RectF(leftx,topy,rightx,bottomy);
canvas.drawArc(oval, strt, arc, true, cPaint);
while (i < 90) {
canvas.drawText(String.valueOf(Character.toChars(i)),f1,f2, tPaint);
break;
}
}
}
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
add the above below setContentView
setContentView(R.layout.activity_new_game);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
You need to set the layout using setContentView and then initialize views.
Note you can findViewById of the current view hierarchy set to the activity
Edit:
Example: This is an example. I don't see why it won't work if you do similar as below.
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".NewGame"
android:id="#+id/relative_layout"
>
<Button
android:id="#+id/prev_button"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/next_button"
android:layout_alignBottom="#+id/next_button"
android:layout_centerHorizontal="true"
android:text="stop_label" />
<Button
android:id="#+id/next_button"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginRight="20dp"
android:layout_toLeftOf="#+id/prev_button"
android:text="start_label" />
<RelativeLayout
android:layout_width="wrap_content"
android:id="#+id/rl"
android:layout_below="#+id/prev_button"
android:layout_height="wrap_content"
>
</RelativeLayout>
</RelativeLayout>
Activity
public class MainActivity extends Activity {
private Button btn1;
private EditText edt1, edt2, edt3, edt4 ,edt5, edt6;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView mv = new MyView(this);
setContentView(R.layout.activity_main);
RelativeLayout layout= (RelativeLayout) findViewById(R.id.rl);
layout.addView(mv);
}
class MyView extends View
{
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.RED);
}
}
}
snapshot
You need to inflate your view before trying to find your relative layout. Try :
RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gameview=new GameView(this);
setContentView(R.layout.activity_new_game);
layout = (RelativeLayout) findViewById(R.id.relative_layout);
//LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//view = mInflater.inflate(R.layout.activity_new_game, gameview, true);
layout.addView(gameview);
}
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
you can't call findViewById before setContentView. Move
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
after setContentView(R.layout.activity_new_game);
you didn't initialize layout in your code so First initialize layout after setContentView then add view to your layout
RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_game);
//Initialize game view
GameView gameview=new GameView(this);
//initialize layout
layout = (RelativeLayout) findViewById(R.id.relative_layout);
//adding game view to layout
layout.addView(gameview);
}
Edit:
initializing like this before setContentView
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
is wrong approach you must initialize views only after setContentView like the above code
class PlayAreaView extends View{
private static final String DEBUG_TAG = "PlayAreaView";
private SeekBar sizeSlider;
private int xMin = 0;
private int xMax;
private int yMin = 0;
private int yMax;
private Rect rect;
private GestureDetector gestures;
private Paint p = new Paint();
private int side = 50;
public PlayAreaView(Context context){
super(context);
rect = new Rect(0,0,side,side);
p.setARGB(255, 255, 255, 255);
GestureListener listener = new GestureListener(this);
gestures = new GestureDetector(listener);
sizeSlider = (SeekBar) findViewById(R.id.seek);
//sizeSlider.setOnSeekBarChangeListener(listener);
}
I am new to developing on Android and am having trouble figuring out what is wrong here. I am getting a NullPointerException at the commented out line. I believe it is because I am asking to findViewById in a class that is not the main activity. If this is indeed the problem how can I access UI elements from this class.
As you have set up, findViewById(R.id.seek) will search for a subview with ID equal to R.id.seek within PlayAreaView, which does not exist since you seem to have the SeekBar in your main layout.
If you must access The SeekBar from within this view, pass in a reference to it while instantiating it, e.g., in the main activity
SeekBar sizeSlider = (SeekBar)findViewById(R.id.seek);
PlayAreaView areaView = new PlayAreaView(this, sizeSlider);
and in PlayAreaView,
SeekBar sizeSlider;
public PlayAreaView(Context context, SeekBar seekBar) {
super(context);
sizeSlider = seekBar;
...
seekBar.setOnSeekBarChangeListener(...);
}
then, the SeekBar instance can be accessed through the instance variable sizeSlider from PlaAreaView.
i'd like to load a picture from sdcard into my view then draw upon it. so far i can take the picture and display it in an imageview after i've drawn a circle on the bitmap but this is not how it should be done. I think that i need to create a custom view class and override it's onDraw(). Atm i have a relative layout with a surfaceview, after the surfaceview i have the imageview and buttons. My question is if i write a custom view class to handle the drawing, i would then pass that to my activity's setContent view, what is confusing me is if the layout is declared declaratively via the xml file, how can i set the activity's setContentView() to the custom view class that handles the drawing?
thanks mat
[edit]
here's the xml layout i'm using. this is not how i should do it using an imageview.
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content" android:gravity="fill">
<ImageView android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"></ImageView>
<com.tecmark.HorizontalSlider android:id="#+id/slider"
android:indeterminateOnly="false"
android:progressDrawable="#android:drawable/progress_horizontal"
android:indeterminateDrawable="#android:drawable/progress_indeterminate_horizontal"
android:minHeight="20dip"
android:maxHeight="20dip" android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
public class LoadPic extends Activity{
private static final String TAG = "Loadpic";
private ImageView imageview;
private File tempFile;
private byte[] imageArray;
private HorizontalSlider slider;
private Canvas canvas;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.e(TAG, " loadpic onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.load2);
setProgressBarVisibility(true);
slider = (HorizontalSlider) this.findViewById(R.id.slider);
slider.setOnProgressChangeListener(changeListener);
imageview = (ImageView)findViewById(R.id.imageView1);
tempFile = new File(Environment.getExternalStorageDirectory().
getAbsolutePath() + "/"+"image.jpg");
imageArray = new byte[(int)tempFile.length()];
try{
InputStream is = new FileInputStream(tempFile);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0) {
imageArray[i] = dis.readByte();
i++;
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 5;
Bitmap bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
Log.e(TAG, bm.toString());
//imageview.setImageBitmap(bm);
Bitmap bmOverlay = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
canvas = new Canvas(bmOverlay);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);
canvas.drawBitmap(bm, new Matrix(), null);
canvas.drawCircle(50, 50, 25, paint);
imageview.setImageBitmap(bmOverlay);
}// end of onCreate
private OnProgressChangeListener changeListener = new OnProgressChangeListener() {
#Override
public void onProgressChanged(View v, int progress) {
// TODO Auto-generated method stub
setProgress(progress);
}
};
}//end of Activity
What i'm thinking of doing is creating a customview class that handles the drawing on the bitmap. But if i do this then how do i make setContentView() to point to my customView class when it point to the xml file. Sorry if i missing something here.
If you want to have a custom view for the bitmap and drawing then you can simply extend ImageView and override the paint method. Something like that:
public class MyImage extends ImageView {
...
#Override
public void paint(...){}
}
And in the xml layout change the ImageView to
<what.ever.package.MyImage ... />