New to Android and having some trouble passing data from an activity to a view. I have a simple Android onCreate method for my Activity.
public class MyActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
int num = intent.getIntExtra(MainActivity.EXTRA_NUM, 0);
setContentView(R.layout.play_game); //this is a MyView class inside of a LinearLayout
//where I want to pass the value of num to MyView
MyView myView = (MyView) findViewById(R.id.myview);
myView.setNum(num);
}
}
public class MyView extends View {
protected int num;
protected int[] array;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
protected void init() {
setBackgroundResource(R.drawable.pic1);
array = new int[num];
}
public void setNum(int num) {
this.num = num;
}
}
However, I can't figure out how to pass a value to the MyView class (it extends View). I just want to send an integer value that the view class will get before starting the constructor.
Add a setter method to yours MyView class
public void setNum(int num)
{
this.num=num;
}
In MyActivity find yours view
MyView myView=(MyView) findViewById(R.id.ID_OF_YOURS_VIEW_IN_ACTIVITYS_LAYOUT);
Set yours value to yours view by passing it to setter method
myView.setNum(num);
Get your view id by findViewById() in oncreate() of MyActivity class
MyView mv=(MyView) findViewById(R.id.your-view-id);
Then set the value by a method getdata()
mv.getdata(value);
where getdata() method looks like
public void getdata(int value)
{
this.value=value;
}
after setContentView
MyView mv = (MyView) findviewById(R.id.myView);
mv.setData(int number);
You'll need to make setData public. Make sure you set the id of myview with
android:id="#+id/myView"
in xml.
You have several options :
Remove initialization of the array from init() or give it a default value for avoiding error as others suggested. It depends whether an array with a default value makes sense or not in your context. Finally inject the number with a setter.
You can also define a static method for setting the number from the activity before the view constructor get called (do it before inflating view with findViewById()). But generatly it is a bad practice and should be used in specific cases.
The real question may be : does the init() call makes sense in constructors and the array must be set at view construction? Can't it be initialized afterward?
Related
I need to pass UI element reference to a non-activity class, no matter what type that element is. And then attach onTouchEvent to that element inside that non-activity class.
How can I do it? I have searched the internet but I didn't find anything helpful.
You pass the context along the constructor or the method call.
Example:
MyNonActivityClass myObject = new MyNonActivityClass(getActivity());
MyNonActivityClass
import android.content.Context;
import your.package.name.R; // notice the R you should add your package
// infront of R it should be something like
// com.example.myapp.R
public class MyNonActivityClass{
private Context context;
public MyNonActivityClass(Context c){
if(context instanceof MyActivityClass){
this.context=c;
}
/** you can do multi if else statements for multi activity classes **/
}
private void someMethodToHandleUi(){
View v = ((MyActivityClass)context).findViewById(R.id.myView);
v.setOnTouchListener(new OnTouchListener(){
// rest of your code
});
}
}
I found solution that doesn't require context or if conditions, all I need to do is to pass element reference to class as object and than use WeakReference to pass reference to a View.
Here is the code:
public class NonActivityClass{
private WeakReference<Object> target;
public NonActivityClass(Object target){
this.target = new WeakReference<Object>(target);
}
#Nullable
public Object getTarget() {
return target == null ? null : target.get();
}
public void doSomethingWithUIElement(){
View view = (View) getTarget();
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
}
}
I want MyView can share data with MyActivity, so I need they can put data into Context and get data from Context, How to do that?
class MyView extends Button {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
put data into context ...
get data from context ...
}
}
class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
put data into context ...
get data from context ...
}
}
I know Activity is a instance of Context, and there is Context in the View's construtor.So I think when the Activity started, At sometime, View is trigger by event, so View put some data in Context, then at sometime, Activity is trigger by event, so it cant get data from 'Context'. I want Context to be a email box which both View and Activity send and get emails from it. I think there is some methods like put(key, val) and get(key) in Context but I not found.
You can get the context by invoking getApplicationContext(), getContext(), getBaseContext(), or this when call it in the activity class.
#malrok44 's idea is inspired me. This is my solution.
interface Interacton {
void putData(key, val)
object getData(key)
}
class MyActivity extends Activity implements Interacton {
public void oncreate() {
getData(xx)
putData(xx,yy)
}
private Map map = new HashMap
public void putData(key, val) {
map.put(key, val);
}
public object getData(key) {
return map.get(key)
}
}
class MyView extends Button {
public MyView(Context context) {
Interaction ctx = (Interaction)context;
ctx.put(xx,yy)
ctx.get(xx)
}
}
I think ThreadLocal is be ok, but I am not sure it is safe?
I want my activity to pass a value to another activity class that extends view. Can you please tell me a solution? I am new to Android Programming.
Better idea is..
class CustomView extends View{
YourData data;
public CustomView(YourData data, Context context){
this.data = data
}
}
and in Activity
new CustomView(data. this)
pass throgh constructor or getter/seller . nothing related to android .
use standard java tequnique to pass data to object .
you can't because intents are used to comunicate between activitys, receivers & services.
You can pass the activity reference in the view and use that to get the appropriate values.
class MyActivity extends Activity {
MyView v;
int i;
public void onCreate(){
v = new MyView(this);
}
}
class MyView extends View {
MyActivity activity;
public MyView(MyActivity act) {
this.activity = act;
}
public void someMethod() {
int valueFromActivity = activity.i;
}
}
In the main class (A.java)
Intent i = new Intent(A.this,B.class);
i.putExtra("val", the value that you want to pass);
startActivity(i);
in B.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
Integer number = getIntent().getIntExtra("val", 0);
We will get the passes value in number
I have a custom view MyView inflated from my_view.xml (with a corresponding Java class MyView.java).
I override MyView(Context context, AttributeSet attrs) to connect subviews up to members of the class.
Now one of these subviews is a Button, and I'd like for my view to listen for a click on its button before passing this event on to a delegate. However if I declare
this.myButton.setOnClickListener(this);
in the constructor MyView(Context context, AttributeSet attrs) (where this is an instance of MyView) I get a NullPointerException.
Where is an appropriate place in MyClass.java to call this.myButton.setOnClickListener(this);?
%%
Edit. Some code:
public MyView(Context ctx, AttributeSet attrs)
{
super(context, attrs);
this.myButton = (Button) this.findViewById(R.id.my_button);
this.myButton.setOnClickListener(this); // Raises null pointer;'id' is correct.
}
Instead of trying to do the setOnClickListener(this) call in the constructor, do it after the button has been fully initialized. Try moving setOnClickListener(this) so that it's called (indirectly) from the parent activity's onResume method like this:
public class MainMenuActivity extends Activity {
#Override
public void onResume() {
super.onResume();
new MyView(this, attrs).onResume();
}
...
}
public class MyView {
public void onResume() {
myButton.setOnClickListener(this);
}
...
}
I use Roboguice all the time for this sort of thing, and highly recommend it. My button handler code looks like this:
class ButtonHandler implements OnClickListener {
#InjectView(R.id.MainMenuButton)
private Button button;
public void onResumeEvent( #Observes OnResumeEvent onResume ) {
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
doSomethingUseful();
}
}
The problem is I've missed off an inflate in the constructor:
LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
i.inflate(R.layout.my_view, this);
This is confusing for me as I'd thought the constructor MyView(Context ctx, AttributeSet attrs) would be called in inflating the view, not the other way around.
I have an activity which creates an object instance of my class:
file MyActivity.java:
public class MyActivity extends Activity {
TextView myView = (TextView)findViewById(R.id.myView);
...
Points myPoints new Points();
...
}
--------------------------------------------------------------
file Points.java:
private class Points {
...
HOW TO USE myView HERE ???
...
}
--------------------------------------------------------------
How do I use the UI objects in my class (which does not extend an
Activity)? Should I pass some context to my Points class? How do I do, exactly?
see you post, i've edited it , to fix the problem
hope it helps :=)
here is the Edit :
file MyActivity.java:
public class MyActivity extends Activity {
TextView myView ;
protected void onCreate(android.os.Bundle savedInstanceState) {
myView = (TextView)findViewById(R.id.myView);
Points myPoints = new Points(this);
myPoints.displayMsg("Hello World !!!");
}
}
--------------------------------------------------------------
file Points.java:
private class Points {
protected MyActivity context;
//add a constructor with the Context of your activity
public Points(MyActivity _context){
context = _context;
}
public void displayMsg( final String msg){
context.runOnUiThread(new Runnable() {
#Override
public void run() {
context.myView.setText(msg);
}
});
}
}
Your Points can't be a private class without being an inner class. So your code doesn't even compile...
Pass the view as parameter to the constructor of your Points class:
public class MyActivity extends Activity {
TextView myView = (TextView)findViewById(R.id.myView);
Points myPoints new Points(myView);
private class Points {
public Points(TextView view) {
// todo
}
}
}
You should do everything and pass back the value to the activity to handle UI instead of doing any UI related stuff in the point stuff.
You can pass the main Activity's context (using Points(getApplicationContext());) to the class as a constructor parameter. You could also pass the specific UI elements you want to manipulate.
A better way to do it, however, may be to have Points not know about the Activity. Have your Activity call Points methods and take the necessary actions based on the method output.
You could just pass the view to your class.
Points myPoints = new Points(myView);
private class Points
{
private TextView mTextView;
Points(TextView textView)
{
this.mTextView = textView;
}
}
i was in same trouble..
i found the simple way..
make a static variable and function ...
call from other class..
TestActivity.java
public class TestActivity extends Activity {
static EditText edit_text1;
public void onCreate(Bundle savedInstanceState)
{
.....
edit_text1 = (EditText) findViewById(R.id.edit_text1);
.....
}
public static void setMSG(String str)
{
edit_text1.setText(str);
}
}
Test2.java
TestActivity.setMSG("this is text");
Could work using an interface
file MyActivity.java:
public class MyActivity extends Activity implements Points.MyListener {
TextView myView;
... onCreate(...){
myView = (TextView)findViewById(R.id.myView);
Points myPoints = new Points();
//pass in MyActivity's instance of the listener
myPoints.addListener(this);
}
#Override
public void updateTextView(String message){
myView.setMessage(message);
}
}
file Points.java:
public class Points {
public Points(){
}
public interface MyListener{
void updateTextView(String message);
}
MyListener myListener;
public void addListener(MyListener listener){
myListener = listener;
}
public void updatePoints(){
//do some operations in calculatePoints()
String points = calculatePoints();
//update views using MyActivity's implementation of updateTextView()
myListener.updateTextView(points);
}
}
Doing it this way, events can be fired / messages sent, for lack of better terms, from the external class to update the Activity UI. This might be overkill if all sb need is to call a method in the Points class that returns something