How to know which Toggle Buttons are clicked from dynamically added view? - java

This is my first time with android programming and I got stuck.
Now I'm trying to add view dynamically which contains toggle buttons, and edittext. However, whenever I select toggle button, options I created only works on last created view.
Options are simple. There are two toggle buttons and they can be clicked mutually exclusive
example
which means whenever I add new views such as B and C in above, the options are only worked on C while not in B. How can I make it to work on every view?
public void onAddField(View v){
LayoutInflater inflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView=inflater.inflate(R.layout.data_gledger_add_new,null);
tbg_add=(ToggleButton)rowView.findViewById(R.id.add_toggle_gledger);
tbc_add=(ToggleButton)rowView.findViewById(R.id.add_toggle_credit);
if(create_box<4){
csl.addView(rowView,csl.getChildCount()-1);
Log.d("create_box",String.valueOf(create_box));
create_box++;
}
else{
Log.d("create_box","full");
create_box=4;
}
tbg_add.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
if(tbg_add.isChecked()){
get_add_cla="menu1";
tbg_add.setTextColor(getResources().getColor(R.color.color_white));
tbc_add.setChecked(false);
tbc_add.setTextColor(getResources().getColor(R.color.color_black));
}
else{
get_add_cla="";
tbg_add.setTextColor(getResources().getColor(R.color.color_black));
}
}
});
//대변 선택
tbc_add.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
if(tbc_add.isChecked()){
get_add_cla="menu2";
tbc_add.setTextColor(getResources().getColor(R.color.color_white));
tbg_add.setChecked(false);
tbg_add.setTextColor(getResources().getColor(R.color.color_black));
}
else{
get_add_cla="";
tbc_add.setTextColor(getResources().getColor(R.color.color_black));
}
}
});
}
I forgot to mention that views are added by clicking button.
android:onClick="onAddField"

The problem almost certainly stems from the fact that you are re-using instance fields (tbg_add and tbc_add) as add new views dynamically.
tbg_add=(ToggleButton)rowView.findViewById(R.id.add_toggle_gledger);
tbc_add=(ToggleButton)rowView.findViewById(R.id.add_toggle_credit);
Because you are re-assigning these fields and also referencing them from the click listeners, you'll always be referencing the most recently created toggle buttons.
Change these to be local variables and everything should work fine.
ToggleButton ledger=(ToggleButton)rowView.findViewById(R.id.add_toggle_gledger);
ToggleButton credit=(ToggleButton)rowView.findViewById(R.id.add_toggle_credit);
Unrelated to your problem, but also something you should fix, is the fact that you're passing null as the second parameter to your inflate() call:
final View rowView=inflater.inflate(R.layout.data_gledger_add_new,null);
When you pass null in this manner, the system won't have any ability to correctly handle the LayoutParams (anything starting with android:layout_ in the xml file) for the newly-inflated view.
You know that you're going to wind up adding the rowView to your csl view, so you should pass that as the second parameter. Once you do that, you also have to pass false as a third parameter to make sure that the inflate() call actually returns the rowView and not its new parent (csl).
final View rowView=inflater.inflate(R.layout.data_gledger_add_new, csl, false);

Related

Adding an onClick to a part of a RecyclerView item

I've been working on an online shop type of application, and I've hit a bump: I've been tasked to add a favorites system, but I can't figure out how to enable pressing a button that's part of the RecyclerView item to add it to favorites.
(In this case, the heart, which is supposed to turn to a full heart when clicked)
Add a boolean value for favourite in your list . Initially , keep it false .
You need to have two drawables , one for selected state and another for unselected state .
In your onBindViewHolder , set the drawable on runtime on the basis of above condition .
if(list.isfav)
{
holder.ivHeart.setImageDrawable(ContextCompat.getDrawable(context,(R.drawable.selected));
}else{
holder.ivHeart.setImageDrawable(ContextCompat.getDrawable(context,(R.drawable.unselected));
}
Put onClick on this ivHeart eg:
holder.ivHeart.setOnClickListener(v -> {
if(list.isfav) {
list[adapterPosition].isfav = false;
}else{
list[adapterPosition].isfav = true;
}
notifyItemChanged(adapterPosition);
});
Dont forget to notify the item while changing item .
In your RecyclerView adapter's onBindViewHolder() method, add click listener to your view and change the drawable programmatically.
The code will be something like this
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
holder.your_like_imageview.setOnClickListener{
holder.your_like_imageview.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.something_else));
};
}
I'm assuming you're using an ImageView for the heart. What you can do is set a click listener on that ImageView and process that click.
An ideal way to do this would be to use an interface to handle click events that you pass to the Adapter.
However you could do something like this in the onBindViewHolder method:
imageView.setOnClickListener {
// depending your logic change the tint for the icon or the drawable
onClick(data[position], addToWishlist)
notifyDataSetChanged()
}
The onClick method will receive the particular item and a flag to add or remove it from
the wishlist:
fun onClick(data: Data, addToWishlist: Boolean) {
// you can perform the addition/ deletion from the wishlist here
}

Android - Finding ID of view from inflated layout

I know there are lots of other answers on stackoverflow on the same thing but I can't seem to get it to work.
What I'm trying to do is find the ID of a view from an inflated layout. I want WV1 to load google.com when the button is clicked, you can see I'm using onClick from XML to do this.
public void ButtonClicked(View view)
{
View inflatedView = getLayoutInflater().inflate(R.layout.tab_content, null);
WV1 = (WebView) inflatedView.findViewById(R.id.tab1WV);
WV1.setWebViewClient(new InsideWebViewClient());
if (WV1.isShown()) {
WV1.requestFocus();
}
else{
}
if (WV1.isFocused()) {
WV1.loadUrl("http://www.google.com");
}
}
This is in the MainActivity, the webview (WV1) is in the other, inflated class.
Problem is, nothing happens at all...
I've been stuck on this for quite some time now, I appreciate all help given to me.. If there's any other information you require then just ask, thanks in advance!
--Edit--
In the MainActivity, theres tabhost and a button that creates new tabs. When new tabs are created the MainActivity inflates the second class file containing the webview, I can't get the mainactivity to find the webview from the inflated class. I dont know if this helps any more or not...
Check out this link:
Android - Add textview to layout when button is pressed
Where one of the answers does this:
mLayout.addView(createNewTextView(mEditText.getText().toString()));
where mLayout is a linear layout in the activity.
You'd have to add a view to one of your current layouts or start up an activity that opens up with a web view in it.
Alternative way to create webview :
Webview WV1 = new WebView(view.getContext);
WV1.setWebViewClient(new InsideWebViewClient());
if (WV1.isShown()) {
WV1.requestFocus();
}
else{
}
if (WV1.isFocused()) {
WV1.loadUrl("http://www.google.com");
}
}
Now add this to a view group
viewgroup.addchild(WV1);
You're not attaching it to anything. You need to either supply the parent when you inflate it, or call addView on the ViewGroup that should contain it.
public void ButtonClicked(View view){
View inflatedView = getLayoutInflater().inflate(R.layout.tab_content, (ViewGroup) findViewById(android.R.id.content));
WV1 = (WebView) inflatedView.findViewById(R.id.tab1WV);
WV1.setWebViewClient(new InsideWebViewClient());
if (WV1.isShown()) {
WV1.requestFocus();
}
if (WV1.isFocused()) {
WV1.loadUrl("http://www.google.com");
}
}
Or:
((ViewGroup)findViewById(android.R.id.content)).addChild(WV1);
Both of these will add your view at the end. You may need to add some layout attributes to get it to look like you want.

Show delete button inside row of a ListView when clicking a button Android

I need to implement a kind of Slide to Delete inside my ListView but what I want is not to slide the row but when the user clicks a button inside the row the delete button should show up. Is it possible? I've already implemented the Button and I know when the user press it but I pretty much have no idea on how to implement the delete button slide in effect from the right of the row.
Can someone give me an Idea on how to start?
If you don't want Swipe-to-delete, then the implementation is pretty simple.
Basically you are gonna show/hide that button on button click.
Since Android ListView reuses the Views, if you show/hide the button of a View of ListItem in onItemClick(), then when the list is scrolled the state will be lost and will result in incorrect behavior.
So we need to maintain this selection state in the Adapter's modal class. Just add a field like selected in the modal class. For instance, if you are showing list of Contact objects, then your modal class will be all like,
class Contact {
private String name;
private String number;
private boolean selected;
..........
}
from what I've understand; you need to implement lets say an edit button, then when user clicks on it, it will disappear and another button called delete will popup instead of it on the same position.
here is a possible approach to achieve that:
in your list_view_adapter.xml:
1-create a frame layout contain both of the buttons on top of each other.
2-default state of delete button is GONE -> android:visibility="gone"
3-when edit is pressed delete button will be visible and you will programmatically set Edit visibility to GONE
4-set your delete button:
#Override
public View getView(final int pos, View convertView, ViewGroup parent) {
View v = convertView;
// Some other things...
Button delete = (Button) v.findViewById(R.id.delete);
delete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// After you delete the object from Parse database here,
notifyDataSetChanged();
}
}

Android: Cannot get a clickable ListView header/footer

I'm trying to set a header and footer in my list view that are clickable buttons. The problem is that the OnClickListener isn't responding to anything and I can't figure out what I'm doing wrong.
$ View header = getLayoutInflater().inflate(R.layout.header_layout, null, true);
getListView().addHeaderView(header);
myAdapter = new myAdapter(this);
header.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do what I want when i click it
}
});
Update
The best solution I ultimately came up with was adding a separate button to the header layout, and then doing it like this:
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
Button headerButton = (Button)header.findViewById(R.id.header_button);
getListView().addHeaderView(header);
headerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// My Click Stuff
}
});
You need to handle the click in the ListView's onItemClick. Simply check if that's the first or last item in the adapter and handle the clicks that way. You need to treat it as an item in the ListView.
I see a few issues:
when inflating the header, use getListView() as the second parameter (root, where you have null now)l
should the header be a View or a ViewGroup? I've ended up using ViewGroup in these situations.
finally -- perhaps you should be setting the click listener on the button in the header instead of the header itself?
There is a way more easier solution:
Just set a "OnClickListener" to the applied View:
View view = inflater.inflate(R.layout.xxx, null);
view.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
//do something
}
});
Very easy thing which solved it!
Example with a footer:
mYourListView.addFooterView(footer, null, true);
Then in the OnItemClickListener you can check:
#Override
public void onItemClick(AdapterView<?> parent,
View view, final int position, final long id) {
if (id != -1) {
// do whatever you do with list items
} else {
// do what you need after the footer been clicked
}
(If you need to handle and the header and the footer click, check position - 0 for the header and [adapter.getCount() - 1] for the footer)
This approach will provide the same visual effect while footer click as if the list item been clicked. (But if you do not need that effect just add OnClickListener to the footer and it will intercept all footer clicks)
i think the listview and buttons are fighting for focus and your listview is winning.
you'll have to use a onTouchListener for the buttons.
There is one more alternative and its to set the following on the footer. There is another method overload created but it did not come up in the docs, i had to check online documentation:
mylistView.addFooterView(footerView, null, false);
where false tells the footer its not selectable. I tested this myself and the buttons inside the footer respond to touches now. I hope this an acceptable answer.
What worked for me:
When inflating the header view, before adding it to the listview, I then used that view to get the subview and add a click listener on it
myHeaderView.findViewById(R.id.myButton).setOnClickListener(new OnClickListener() { ... } );
also, when I added it to the listView, I used the overloaded constructor with the third variable set to true
mListView.addHeaderView(myHeaderView, null, true);

Updating Android Tab Icons

I have an activity that has a TabHost containing a set of TabSpecs each with a listview containing the items to be displayed by the tab. When each TabSpec is created, I set an icon to be displayed in the tab header.
The TabSpecs are created in this way within a setupTabs() method which loops to create the appropriate number of tabs:
TabSpec ts = mTabs.newTabSpec("tab");
ts.setIndicator("TabTitle", iconResource);
ts.setContent(new TabHost.TabContentFactory(
{
public View createTabContent(String tag)
{
...
}
});
mTabs.addTab(ts);
There are a couple of instances where I want to be able to change the icon which is displayed in each tab during the execution of my program. Currently, I am deleting all the tabs, and calling the above code again to re-create them.
mTabs.getTabWidget().removeAllViews();
mTabs.clearAllTabs(true);
setupTabs();
Is there a way to replace the icon that is being displayed without deleting and re-creating all of the tabs?
The short answer is, you're not missing anything. The Android SDK doesn't provide a direct method to change the indicator of a TabHost after it's been created. The TabSpec is only used to build the tab, so changing the TabSpec after the fact will have no effect.
I think there's a workaround, though. Call mTabs.getTabWidget() to get a TabWidget object. This is just a subclass of ViewGroup, so you can call getChildCount() and getChildAt() to access individual tabs within the TabWidget. Each of these tabs is also a View, and in the case of a tab with a graphical indicator and a text label, it's almost certainly some other ViewGroup (maybe a LinearLayout, but it doesn't matter) that contains an ImageView and a TextView. So with a little fiddling with the debugger or Log.i, you should be able to figure out a recipe to get the ImageView and change it directly.
The downside is that if you're not careful, the exact layout of the controls within a tab could change and your app could break. Your initial solution is perhaps more robust, but then again it might lead to other unwanted side effects like flicker or focus problems.
Just to confirm dominics answer, here's his solution in code (that actually works):
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
if (TAB_MAP.equals(tabId)) {
ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_black));
iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_white));
} else if (TAB_LIST.equals(tabId)) {
ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_white));
iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_black));
}
}
});
Of course it's not polished at all and using those direct indices in getChildAt() is not nice at all...
See my post with code example regarding Customized Android Tabs.
Thanks
Spct
This is what I did and it works for me. I created this function in the activity that extends from TabBarActivity
public void updateTab(int stringID) {
ViewGroup identifyView = (ViewGroup)getTabWidget().getChildAt(0);
TextView v = (TextView)identifyView.getChildAt(identifyView.getChildCount() - 1);
v.setText(stringID);
}
You can modify this function to change the image instead of text or you can change both, also you can modify this to get any tab child. I was particularly interested in modifying the text of the first tab at runtime.
I called this function from the relevant activity using this call
getParent().updateTab(R.string.tab_bar_analyze);
Try This:
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
if (TAB_MAP.equals(tabId)) {
ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_black));
iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_white));
} else if (TAB_LIST.equals(tabId)) {
ImageView iv = (ImageView) tabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_map_white));
iv = (ImageView) tabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.icon);
iv.setImageDrawable(getResources().getDrawable(R.drawable.tab_list_black));
}
}
});

Categories

Resources