I use the ViewPager from the compatibility pack to page fragments.
I want to have a background service which serves the fragments with data. Therefore I use a "normal java class" to update (for example) a TextView in such a fragment:
public class Updater {
private Activity mActivity=null;
private TextView tv = null;
private Context mContext;
private View mInflatedMenu =null;
public Updater (Activity _activity, Context _context, View inflatedMenu) {
mActivity = _activity;
mContext = _context;
mInflatedMenu = inflatedMenu;
}
public void updateTextView (String _text) {
tv = (TextView) mInflatedMenu.findViewById(R.id.tvFragment1Updater);
tv.setText(_text);
Toast.makeText(mContext, tv.getText(), Toast.LENGTH_SHORT).show();
}
}
The Toast says, that the TextView has the value of the parameter _text. That's okay!
The problem: On the screen the original value of the TextView hasn't changed to _text.
I think I've tried all kinds of invalidate(). What I'm doing wrong? How would you update your fragment "views" in a ViewPager?
You need to save the toast instance, when you are changing the vlaue of _text, you neen to hide the old toast and create a new one.
Related
After much research and tutorial hunting, I've come to find some answers to questions I had on my own. Now, my last question is this: If I have a View instance variable carrying over from the previous Activity, and it isn't working to refine the findViewbyId() function to the current source file, what should I take my View as, to instance my findViewById()?
Here's the code I have:
public class login_fb extends Activity implements View.OnClickListener {
private static final String EMAIL = "email";
private static AccessToken accessToken = null;
private static boolean isLoggedIn = false;
private static String deduction = "";
private static String income = "";
private static CallbackManager callbackManager = CallbackManager.Factory.create();
private static boolean hasItemized = false;
private FireMissiles fireMissiles = new FireMissiles();
public void gotoRcpts (View view)
{
signIn( view );
}
public void getSuggestions(View view) throws ParserConfigurationException, ParseException, SAXException, IOException {
checkPermsOfStorage( this );
setContentView( R.layout.content_search );
Intent intent = Intent.makeMainActivity( lists.newComponentActivity().getComponentName() );
startActivity( intent );
lists listing = new lists(view, view.getContext()); //everything works to here.
listing.display( view ); // This is where I call the function below.
}
Here's the second half of the code
public void display(View view)
{
// I feel the issue is here, but why can I get
listViewP = view.findViewById( R.id.view_personal );
listViewB = view.findViewById( R.id.view_business );
// now create an adapter class
Log.d("&&&&", String.valueOf(this.mpTitle.size()));
if (this.mpTitle != null && listViewP != null) { //if I don't check for null, error
MyAdapter adapterP = new MyAdapter( this, listed_views, mpTitle, content_search, mContext);
listViewP.setAdapter( adapterP ); // here's where my error is.
}
if (this.mbTitle != null && listViewB != null) { // if I don't check for null error
MyAdapter adapterB = new MyAdapter( this, listed_views, mbTitle, content_search, mContext);
listViewB.setAdapter( adapterB ); // here also there's an error.
}
}
The two ListViews are view_personal, and view_business.
A View is a UI component - when your Activity starts, you usually call setContentView in onCreate, passing in an XML layout file. What that does is construct all the different Views in your layout file, setting their parameters, and assigning things like the id you've given them.
So you end up with a layout hierarchy, with things like a TextView that has an id of titleText or whatever. You can find that specific object by calling findViewById() on a View (usually the top-level layout), and it will search all that View's descendants in the layout hierarchy, until it finds one matching that ID name.
Those Views are all instances that get created, if you destroy the activity and recreate it you'll have a whole new set of view objects. So you're not keeping instances (and you definitely shouldn't try to either!), and if you go to another Activity, you definitely aren't seeing the same view objects again.
So when you call findViewById in the new activity, using the same id as in the last activity, you're not finding the same instance of a View object - you're just finding one that's been assigned the same ID. You can reuse IDs like this, the only problem is if you have more than one in the same layout hierarchy - findViewById will only find the first one that matches.
If you're getting null references for listViewP etc., you don't have a view with that ID in your layout (or at least, not under the View you're calling findViewById on). If they exist in another Activity, then you can't access them - that activity isn't running, it doesn't exist. If ActivityB wants to change something in ActivityA, it needs to pass data to it, so ActivityA can handle it.
I am having adapter class, In that, I need to pass invoiceId to an Activity Class. I have seen some example like pass-through interface, but I lost track on following the code procedure.
Here Is My Adapter Class extends BaseAdapter
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
companyName = ct.getSharedPreferences("prefs", 0);
Log.d("test", "" + deliveryListBeans.size());
LayoutInflater inflater = (LayoutInflater) ct.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.list_vew_for_delivery_order, null);
TextView invoice = (TextView) v.findViewById(R.id.invoice);
final TextView delivery = (TextView) v.findViewById(R.id.do_delivery);
final DeliveryListBean dlb = deliveryListBeans.get(position);
invoice.setText(dlb.getInvoiceNo());
}
delivery.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ct.startActivity(new Intent(ct, EmployeesListForPopUp.class));
DeliveryOrdersListAdapter deliveryOrdersListAdapter=new DeliveryOrdersListAdapter(EmployeesListForPopUp.this);
}
});
}
Here is My Activity Class
public class EmployeesListForPopUp extends Activity {
private List<EmployeeIdNameBean> employeeIdNameBeans = new ArrayList<EmployeeIdNameBean>();
ListView listView;
SharedPreferences companyName;
EmployeePopUpAdapter employeePopUpAdapter;
private ImageView img1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_employees_list_for_pop_up);
I need to get invoiceId from Adapter Class. How?
You need to pass context of the activity in adapters constructor.
Then set activity.invoiceid value in clickevents of adapter.
One simple way is that you write a method in MainActivity
public void setInvoiceId(int invoiceId) {
// do what you want with invoiceId
}
and pass the instance of your activity to adapter
DeliveryOrdersListAdapter adapter = new DeliveryOrdersListAdapter(EmployeesListForPopUp.this);
and get it in your adapter and keep it
EmployeesListForPopUp myActivity;
public MyAdapter(EmployeesListForPopUp activity) {
myActivity = activity;
}
and where you need to pass invoiceId just call the method of main activity
myActivity.setInvoiceId(invoiceId);
General way of implementing it:
In the adapter class, where you set text to invoice TextView, you also can add a tag to it. Put attention - despite every item in the list is build from the same prototype, the tag (as well as text) will be uniq. The best way is to use "position" as value of the tag: invoice.setText(dlb.getInvoiceNo());
invoice.setTag(Integer.valueOf(position).toString());
You need to make your items in the list clickable (this is out of the scope of this question). So, when you click on some item - you can retrieve any data it has, and specifically tag - getTag();.
Then you send Intent to other activity, providing the tag as extra message. So that activity will "know" which item in the array list it is related to (i.e. tag == position, right?). And continue from there.
I implemented simple project that illustrates it. This project is simple demo and illustration of working with ArrayList adapter,
displaying the item in the ListView, clicking on some item and display relevant data in separated activity. Please download it and try (min API 21). Basic description is available in README file.
The project is here on the GitHub:
(corrected path)
https://github.com/everall77/ArrayListSimpleExmpl
What am i trying to do?
I have a RecyclerView which keeps rows and looks like a ListView. Rows of these list are defined at feed_listview_row.xml. I have a RecyclerAdapter for this RecyclerView and it is called Feed_Recycler_Adapter.java which you can see down below.
I want to show an AlertDialog when user Long clicked one of these rows. There is a question about if user want to delete this row or keep it. After user accept to delete the row. There will be SnackBar to notify user and give her/him a last chance to take it back.
Problem
I can't view the SnackBar because I am not able to show the CoordinatorLayout.
Code
Feed_Recycler_Adapter.java
holder.layout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
cl = (CoordinatorLayout) v.findViewById(R.id.FeedCoordinatorLayout);
/*this row above is failing to fill the cl variable.
This cl variable returns null! I need to get the coordinatorlayout for snackbar*/
String selectedListId = mDataset.get(position).getListId();
String selectedPostId = mDataset.get(position).getPostId();
Push_Options.ownerOrfollower(v.getContext(), selectedListId, selectedPostId, cl);
return true;
}
});
I tried
I tried to inflate the content_feed at the Feed_Recycler_Adapter.ViewHolder onCreateViewHolder and using it as a view to get FeedCoordinatorLayout, did not solve the problem but I didn't get any error simply because cl wasn't null. But didn't show the SnackBar either.
I read some part of your huge question and find that you need to rootView (coordinatorLayout)
this maybe help you :
add constructor to YourAdapter with Context param:
public yourAdapter(Context activity){
context = activity // context is local object
}
now in your activity where you create an instance of YourAdapter do this :
adapter = new YourAdapter(YourActivity.this);
and when you want to show snakBar :
Snackbar.make(((YourActivity) context).coordinatorLayout, "Post deleted.", Snackbar.LENGTH_LONG).show()
sure to define coordinatorLayout in YourActivity class .
I found the solution with a little bit of help from dariush f's answer.
I modified my existing constructor to have a CoordinatorLayout field.
class Feed_Recycler_Adapter extends RecyclerView.Adapter<Feed_Recycler_Adapter.ViewHolder> {
public static String TAG = "Feed Recycler Adapter";
private CoordinatorLayout cl;
private ArrayList<Feed_List_Class> mDataset;
//CoordinatorLayout cl;
// Provide a suitable constructor (depends on the kind of dataset)
Feed_Recycler_Adapter(ArrayList<Feed_List_Class> myDataset,CoordinatorLayout coordinatorLayout) {
cl=coordinatorLayout;
mDataset = myDataset;
}
And i am sending the coordinator layout when i instantiate this adapter. Like this:
CoordinatorLayout cl = (CoordinatorLayout) findViewById(R.id.FeedCoordinatorLayout) ;
mAdapter = new Feed_Recycler_Adapter(posts,cl);
Since my onLongClick method is already inside my Adapter class i can create a snackbar with my cl variable which is set by my constructor.
Push_Options.ownerOrfollower(v.getContext(), selectedListId, selectedPostId, cl);
i am trying to add extra input fields on the fly to my view.
i first read json string from url with an async funct and map this dynamically to an object with a hasmap with GSON.
next i want to iterate the hashmap to create and add the input fields:
public class NewProductActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_product);
TextView view = (TextView) this.findViewById(android.R.id.content);// is this the correct way to get view?
new loadTemplateAttributes(view).execute();// android studio complains about passing view here
.. snip...
class loadTemplateAttributes extends AsyncTask<String, String, HashMap> {
HashMap mymap;
.. snip...
protected void onPostExecute(HashMap mymap) {
pDialog.dismiss();
Iterator it = mymap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
String name = (String) pair.getKey();
TemplateAttribureProperties t = (TemplateAttribureProperties) pair.getValue();
String type = t.getType();
System.out.println("Name=" + name + " type=" + type);
LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout2);
// add text view
TextView tv = new TextView(this); // 'this' is unknow here
tv.setText(name);
ll.addView(tv);
EditText et = new EditText(view); // 'view' is what i want to pass but dont know how
et.setText();
ll.addView(et);
it.remove();
}
problem is that 'this' is unknown inside onPostExecute function.
i read something about passing the view to the async function but to me it is unclear how to get the view in the firstplace and how to pass it after...
also a lot of options dont seem to work because they are deprecated or are unsafe because the might introduce memory leaks according to the comments.
really lost here.
I don't know what you are doing but You can use Context context; and TextView view; before onCreate() making it global and then you can callTextView tv = new TextView(context); in your method.
public class NewProductActivity extends Activity {
Context context=this;
private TextView view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_product);
view = (TextView) findViewById(android.R.id.content);
}
new loadTemplateAttributes(view).execute();// android studio complains about passing view here
you would have to add constructor to your asynctask, like that:
class loadTemplateAttributes extends AsyncTask<String, String, HashMap> {
View view;
public loadTemplateAttributes(View v) {
view = v;
}
TextView tv = new TextView(this); // 'this' is unknow here
from internal class in java, you refer to parent class using NewProductActivity.this syntax in your case.
EditText et = new EditText(view); // 'view' is what i want to pass but dont know how
et.setText();
you could use aproach with constructor as I described above, or refer directly to activity view: NewProductActivity.this.view. But you would have to make view a class field in your activity.
Advanced: making your activity an internal class instead of static, and also passing views to it, might cause reference leaks and also crashes in case you use view (inside AsyncTask) that was invalidated due to screen rotation. This is especially possible if your AsyncTask is doing network operations. To prevent it always make AsyncTasks static, also if you pass views or activities to them, then wrap those references in WeakReference<>
I don't manage to set a neither a title nor a (title) icon to my custom alert dialog.
My code:
public class AddingFavoriteDialog extends AlertDialog {
private OnAddingFavoriteListener onAddingFavoriteListener;
private Context context;
private GeocodingManager geocodingManager;
private FavoritesActivity favoritesActivity;
public AddingFavoriteDialog(Context context, OnAddingFavoriteListener onAddingFavoriteListener) {
super(context, android.R.style.Theme_Dialog);
this.context = context;
this.onAddingFavoriteListener = onAddingFavoriteListener;
this.geocodingManager = new GeocodingManager(context);
this.favoritesActivity = (FavoritesActivity) context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adding_favorite_dialog2);
setTitle("MYTITLE");
setIcon(R.drawable.star_gold);
}
What am i doing wrong? I also tried to set it by calling super.setTitle("MYTITLE"); in onCreate() as well as in the constructor.
EDIT: Even setButton(BUTTON_POSITIVE, context.getString(R.string.button_value_OK),
new OnClickListener() {...} seems not to work.
Use setView instead of setContentView, because setContentView replaces everything in the AlertDialog, including the default title bar and icon (and buttons etc.). Instead, setView only replaces the middle part (the message, if you will).
Use LayoutInflater if you need to.
Extending Dialog instead of AlertDialog will fix the problem.