I have an app with vertical slider to switch between different smileys (from happier to saddest)
My problem is i don't know how I can get currentItem of my ViewPager (When User is on a specific smiley)
I've tried
verticalViewPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mPreferences.edit().putInt(PREF_KEY_CURRENT_SMILEY,verticalViewPager.getCurrentItem()).apply();
return false;
}
});
And in the other activity (where i have to store the current smiley selected) :
currentSmileyInt = mPreferences.getInt(PREF_KEY_CURRENT_SMILEY,-50);
currentSmileyString = Integer.toString(currentSmileyInt);
currentSmileyTextView.setText(currentSmileyString);
If i'm good the textview on the other activity should display an int between 1-6. (different positions), and if i'm not good it display -50.
I don't understand what i'm doing wrong, as i set verticalVP.setCurrentItem(3) the corresponding smiley is displayed ...
Thank you in advance and sorry for my bad english :)
**You can use ViewPager.OnPageChangeListener**
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
final SharedPreferences.Editor editor = pref.edit();
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
currentPage=position;
Toast.makeText(MainAsyncActivity.this, "position: "+position, Toast.LENGTH_SHORT).show();
editor.putInt("key_name",currentPage); // Storing integer
editor.commit(); // commit changes
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
**get stored value from SharedPreferences**
int currentSmileyInt= pref.getInt("key_name", 0);
Log.d("Keyname: ", String.valueOf(currentSmileyInt));
String currentSmileyString = Integer.toString(currentSmileyInt);
currentSmileyTextView.setText(currentSmileyString);
why don't you just use getcurrentItem method from viewpager. like following, will give you the pageNumber of the view pager.
// getting current Page
int page = mPager.getCurrentItem();
This method getCurrentItem will work for you to get a position of ViewPager fragment and you can use like this following:
((YourActivity)getActivity()).verticalViewPager.getCurrentItem());
YourActivityis where you are exactly using the ViewPager with adapter and getActivity() is the Context as a reference of your fragment and do not forget to make verticalViewPager object as public access specifier.
Is there any way to place the image on the last line of the TextView
I use setCompoundDrawablesWithIntrinsicBounds. Some ideas about it will be good.
Also i need to handle clicks on my image only. This behavior is represented by the following code :
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.info, 0);
textView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= textView.getRight() - textView.getTotalPaddingRight()){
listener.onAddressClicked(livingAreas);
return true;
}
}
return true;
}
});
With Text view you can set a drawable on a determinated position.
You can use this xml example:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableBottom="#drawable/image"
android:text="blablabla"/>
Programmatically:
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)
text_view.setCompoundDrawables(null, null, null, getDrawable(drawable_image_id));
Use SpannableString so that you can include image in your text. For code sample, check this question and answer
I have a TextView that contains a DrawableRight, what I want to do is detecting when the user presses that icon in drawableRight, is that possible ? and if it is how can I do it ?
PS: I am working inside a fragment
TextView XML
<TextView
android:id="#+id/mTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="false"
android:textSize="22dp"
android:drawableRight="#mipmap/icn" //this is the drawable
/>
mTitle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_RIGHT = 2;
if (event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() >= (mTitle.getRight() - mTitle.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
//drawable pressed
return true;
}
}
return false;
}
});
I want to be able to respond to a click event on a disabled switch, is that possible?
I have a switch that is not enabled until the user fills in some information, so it looks like this:
I want to prompt the user to fill out the information if they click on the disabled switch with a dialog, like so:
mySwitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!userInfo.isFilled){
new AlertDialog.Builder(MainActivity.this)
.setTitle("Fill out info first!")
.setMessage("You must first fill out info before turning on this featurel")
.setNeutralButton("Okay", null)
.show();
}
}
});
However, the onClick() is not triggered when I click on the disabled switch, so how do I get when the user clicks on it?
You could place a transparent View on top of the Switch and toggle its enabled state opposite the Switch, and show the message when this overlaid View is clicked.
From the View.java source code,
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
if (event.isTargetAccessibilityFocus()) {
// We don't have focus or no virtual descendant has it, do not handle the event.
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
// We have focus and got the event, then use normal event dispatch.
event.setTargetAccessibilityFocus(false);
}
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
// Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn't want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}
the enabled flag ensures the UnhandledEvents are consumed however not passed along to the listeners,thereby bypassing all your possible code.So it is not possible to listen to events on a disabled view.
That said, your options are,
Change the style to mimic that of a disabled view as mentioned here,and then add your required functionality.
Add a overlay invisible view to perform your required functionality which you can set to Gone once the view should be enabled.
Use something apart from enabled,(you could setClickable(false) and consume touch events)
You can set onTouchListener and react to boolean (e.g isToggleEnable) reference with respect to the user's previous actions:
mySwitch.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(!isToggleEnable){
//Taost here
}
//If isToggleEnable = false on return OnClickListener won't be called
return isToggleEnable;
}
});
When it is disabled, setEnabled(false), these listeners won't work.
Try this way: don't disable it, use the setOnCheckedChangeListener and check against your is-entry-filled in there:
use setOnCheckedChangeListener
switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isEntryFilled) {
buttonView.setChecked(false);
// your alert dialog
} else {
}
}
});
this will re-check it back to off and pop your alert, until isEntryFilled is met.
EDIT
OR instead of setEnabled(false), use setClickable(false) or android:clickable="false" since docs say setClickable() is tied to click-events.
and instead of OnClickListener, try OnTouchListener. It will register your on-down-touch (and ignore your on-up-touch), since a click consists of down+up.
switch.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!isEntryFilled) {
buttonView.setChecked(false);
// your alert dialog
}
return false;
}
});
then somewhere else, where you check for isEntryFilled, reactivate your switch with switch.setClickable(true)
Try setting setFocusable(false) and setEnabled(true) on your switch. That way, click events will be fired while the switch still being "disabled". Taken from this answer.
mySwitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isClick()){
//Your Valid Code
}else{
//Make our switch to false
new AlertDialog.Builder(MainActivity.this)
.setTitle("Fill out info first!")
.setMessage("You must first fill out info before turning on this featurel")
.setNeutralButton("Okay", null)
.show();
}
}
});
public Boolean isClick(){
//check condition that user fill details or not
//if yes then return true
// else return false
}
Let the Parent View intercept ClickEvents or TouchEvents, when its detected check if the receiving View is disabled, and do what you have to do.
Edit
"it doesn't work when disabled?"
try these codes, Im use LinearLayout for easy aligment. but overall it should give you an example
this is a full example
XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="70dp"
android:background="#273746">
<FrameLayout
android:layout_width="match_parent"
android:id="#+id/ass"
android:background="#drawable/abc_popup_background_mtrl_mult"
android:layout_height="match_parent">
</FrameLayout>
MainActivity onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_entry_screen);
FrameLayout fl = (FrameLayout)findViewById(R.id.ass);
Test t = new Test(this);
FrameLayout.LayoutParams lp = (LayoutParams) fl.getLayoutParams();
lp.height = LayoutParams.MATCH_PARENT;
lp.width = LayoutParams.MATCH_PARENT;
t.setOrientation(LinearLayout.VERTICAL);
t.setLayoutParams(lp);
fl.addView(t);
t.setBackgroundColor(Color.YELLOW);
Button b = new Button(this);
b.setText("patricia");
t.addView(b);
b = new Button(this);
b.setText("monica");
t.addView(b);
b = new Button(this);
b.setText("rebecca");
t.addView(b);
}
Test.java
public class Test extends LinearLayout {
public Test(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
StringBuilder sb = new StringBuilder();
sb.append("intercept \n\r");
int x = (int)event.getX(),
y= (int)event.getY();
for(int i =0; i< getChildCount(); i++){
int[] pos = new int[]{getChildAt(i).getLeft(),getChildAt(i).getTop(),
getChildAt(i).getMeasuredWidth(),
getChildAt(i).getMeasuredHeight()};
sb.append(getChildAt(i).getLeft()+", ");
sb.append(getChildAt(i).getTop()+", ");
sb.append(getChildAt(i).getMeasuredWidth()+", ");
sb.append(getChildAt(i).getMeasuredHeight());
sb.append("\n\r");
sb.append(isInBounds(pos, x, y));
sb.append("\n\r");
}
sb.append("x is ");
sb.append(x);
sb.append("y is ");
sb.append(y);
Toast.makeText(getContext(),sb.toString() , Toast.LENGTH_LONG).show();
return super.onInterceptTouchEvent(event);
}
private boolean isInBounds(int[] dimen, int x, int y){
return ((x >= dimen[0] && x < (dimen[0] + dimen[2]))
&& (y >= dimen[1] && y < (dimen[1] + dimen[3])));
}
}
Now The one you click will check out to be true, that is the child, now when it checks out to be true you can do something like this
View v = getchildAt(pos);
//its the one that is tapped or clicked
if(!v.isEnabled()){
//this is the guy you want now, do what you want to do
for click event i am not try this, but you could just do View.performClick() or put your Dialog in the ViewGroup class and call it
actually you could use the View..getClipBounds() to save yourself from int array
Set the disable switches on click listener to change the listeners of the other switches. For example:
Switch s = (Switch) findViewById(R.id.SwitchID);
if (s != null) {
s.setOnCheckedChangeListener(this);
}
/* ... */
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(this, "The Switch is " + (isChecked ? "on" : "off"),
Toast.LENGTH_SHORT).show();
if(isChecked) {
//do stuff when Switch is ON
//this is where you set your normal state OnClickListner
} else {
mySwitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!userInfo.isFilled){
new AlertDialog.Builder(MainActivity.this)
.setTitle("Fill out info first!")
.setMessage("You must first fill out info before turning on this featurel")
.setNeutralButton("Okay", null)
.show();
}
}
});
}
}
I'm guessing you've disabled the switch using switch.setEnabled(false). If so, the onclick event will not trigger. If you still want to handle a click action when the switch is disabled, you can use .setOnTouchListener()...
You're best bet however would be to use .setOnCheckedChangeListener() and keeping the switch enabled. Basically when onCheckChanged() gets called, you can popup your dialog if the switch value is on and when the user click ok, you default the switch back to off.
mSwitched.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (checked && !userInfo.isFilled){
new AlertDialog.Builder(Activity.this)
.setTitle("Fill out info first!")
.setMessage("You must first fill out info before turning on this featurel")
.setNeutralButton("Okay", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
mSwitched.setChecked(false);
}
})
.show();
}
}
});
You can do this in a different way,Give a root layout to toggle button with same width and height of toggle button
<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"
>
<!--Root layout to toggle button with same height and width
of toggle button-->
<LinearLayout
android:layout_width="wrap_content"
android:id="#+id/linear"
android:layout_height="wrap_content">
<ToggleButton
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
/>
</LinearLayout>
</RelativeLayout>
When you disable the button,make the button as not focasable and clickable .Then os will handover touch functionality to rootlayout.In the root layout click listner we can write the click logic when the button is not enabled
public class MainActivity extends AppCompatActivity {
ToggleButton button;
LinearLayout linearLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (ToggleButton) findViewById(R.id.button);
linearLayout= (LinearLayout) findViewById(R.id.linear);
//disabling button
button.setEnabled(false);
button.setClickable(false);
button.setFocusableInTouchMode(false);
button.setFocusable(false);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//write the logic here which will execute when button is enabled
}
});
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//write the logic here which will execute when button is disabled
}
});
}
}
When you enable the button,make button to clickable and focausable.
//enabling button
button.setEnabled(true);
button.setClickable(true);
button.setFocusableInTouchMode(true);
button.setFocusable(true);
I have 6 checkboxes and I would want for example if I have a variable a=2 to let the user check 2 checkboxes and make the other disabled..if I have a=3 to let the user check 3 checkboxes and disable the rest and so on..This is what I tried:
public void itemClicked(View v) {
//code to check if this checkbox is checked!
CheckBox checkBox = (CheckBox)v;
check1=(CheckBox)findViewById(R.id.check1);
check2=(CheckBox)findViewById(R.id.check2);
check3=(CheckBox)findViewById(R.id.check3);
check4=(CheckBox)findViewById(R.id.check4);
check5=(CheckBox)findViewById(R.id.check5);
check6=(CheckBox)findViewById(R.id.check6);
if(a==1)
{
only one can be checked the others get disabled
}
}
}
and a part of the xml file is:
<CheckBox android:id="#+id/check1"
android:layout_width="140dp"
android:layout_height="250dp"
android:scaleX="1.0"
android:scaleY="1.0"
android:button="#layout/cb_selector"
android:layout_marginLeft="80dp"
android:layout_marginTop="505dp"
android:onClick="itemClicked"
/>
<CheckBox android:id="#+id/check2"
android:layout_width="140dp"
android:layout_height="250dp"
android:scaleX="1.0"
android:scaleY="1.0"
android:button="#layout/cb_selector"
android:layout_marginLeft="365dp"
android:layout_marginTop="505dp"
/>
How can I achive this?
You need an array of checkboxes and a your check of variable in onCheckedChange.
CheckBox[] cba;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cba = new CheckBox[]{
(CheckBox)findViewById(R.id.check1),
(CheckBox)findViewById(R.id.check2),
(CheckBox)findViewById(R.id.check3),
(CheckBox)findViewById(R.id.check4),
(CheckBox)findViewById(R.id.check5),
(CheckBox)findViewById(R.id.check6)
};
//here set onChechedChange for all your checkboxes
for (CheckBox cb:cba) {
cb.setOnCheckedChangeListener(cbListener);
}
}
CompoundButton.OnCheckedChangeListener cbListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkEnoughAndMakeDisabled(cba);
}
};
private void checkEnoughAndMakeDisabled(CheckBox checkBoxes[]){
int countChecked =0;
for (CheckBox cb:checkBoxes){
cb.setEnabled(true);
if (cb.isChecked()) countChecked++;
}
//your variable
if (a <= countChecked) {
for (CheckBox cb:checkBoxes){
if (!cb.isChecked())cb.setEnabled(false);
}
}
}
Ps: Also i think the best practice for such issues is usage of Data-Binding, but it is other story
If there's a case where the user can select only one option, you better use radio buttons.
Anyway, here's a good and simple answer: https://stackoverflow.com/a/20041237/5280641.