In this example the contentScrim attribute is set with a color, but I can't figure out how to control when it starts. I woud like to start the color transition sooner.
Can you give me a hint? Thanks in advance.
You'd have to create a class that extends CollapsingToolbarLayout. Something like this (you might need to adjust that so it exactly fits your needs):
public class CustomCollapsingToolbarLayout extends CollapsingToolbarLayout {
public static interface Listener {
public void onContentScrimAnimationStarted(boolean showing);
}
private Listener mListener;
public CustomCollapsingToolbarLayout(Context context) {
super(context);
}
public CustomCollapsingToolbarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomCollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setScrimsShown(boolean shown, boolean animate) {
super.setScrimsShown(shown, animate);
if (animate && mListener != null) {
mListener.onContentScrimAnimationStarted(shown);
}
}
public void setListener(Listener listener) {
mListener = listener;
}
}
And just call setListener on your CustomCollapsingToolbarLayout instance.
CustomCollapsingToolbarLayout mToolbarLayout =
(CustomCollapsingToolbarLayout) findViewById(R.id.toolbar_layout);
mToolbarLayout.setListener(new Listener() {
#Override
public void onContentScrimAnimationStarted(boolean showing) {
//do what you want
}
});
EDIT (actually answering the question):
Modify the scrimVisibleHeightTrigger value (with the setScrimVisibleHeightTrigger method of the CollapsingToolbarLayout) to change the starting point of the animation.
Related
I am trying build simple library for button,
inside library folder I created below class
public class SimpleImageButton extends AppCompatImageView implements AppCompatImageView.OnClickListener{
public Context mContext;
Activity activity;
public SimpleImageButton (Context context) {
super(context);
mContext = context;
setCustomTypeface(context, null);
}
public SimpleImageButton (Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setCustomTypeface(context, attrs);
}
public SimpleImageButton (Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
mContext = context;
setCustomTypeface(context, attrs);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setCustomTypeface(Context context, AttributeSet attrs) {
if(isInEditMode())
return;
TypedArray a = context.obtainStyledAttributes(attrs,
android.support.v7.appcompat.R.styleable.TextAppearance);
setBackground(ContextCompat.getDrawable(mContext,
R.drawable.applogo_ads));
a.recycle();
}
public void onClick(View view) {
// here i have some functions to execute
}
}
and my Mainclass in App folder
SimpleImageButton imgBtn= (SimpleImageButton )findViewById(R.id.clickButton);
imgBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
imgBtn.onClick(view);
// without this line how can i reach to onclick() of simpleImageButton class
}
});
so it is woking fine when i click button. but i want to make library button to work directly, without onClick function inside main activity, on clicking button should directly redirect to SimpleImageButton class onclcik method
I am very new to stack overflow , if any mistakes in the grammar / way of asking question please never mind.
thank you.
Use setOnClickListener(this) inside your view's constructor.
public SimpleImageButton (Context context) {
super(context);
mContext = context;
setCustomTypeface(context, null);
setOnClickListener(this);
}
I just override the this dispatchTouchEvent and dispatchKeyEvent and
create own public function setOnClickListener(OnClickListener listener) to set on click listener
public class SimpleImageButton extends AppCompatImageView{
//...
private OnClickListener listener;
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (listener != null) listener.onClick(this);
}
return super.dispatchTouchEvent(event);
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER || event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
if (listener != null) listener.onClick(this);
}
return super.dispatchKeyEvent(event);
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
}
Now I hope it will be clickable just like other buttons.
I recently used TextInputLayout and it's setError() method. The problem I'm getting is, when I clear the error by calling setError(null) it leaves so much of empty space at the bottom.
Normal:
With error:
After clearing error:
After looking at the source, I found that they are making the view INVISIBLE instead of GONE
.setListener(new ViewPropertyAnimatorListenerAdapter() {
#Override
public void onAnimationEnd(View view) {
view.setVisibility(INVISIBLE); // here it is
updateLabelVisibility(true);
} }).start();
I'm wondering why is it so? How to resolve this to avoid the empty space?
Check out the docs for
public void setErrorEnabled (boolean enabled)
It says
Whether the error functionality is enabled or not in this layout.
Enabling this functionality before setting an error message via
setError(CharSequence), will mean that this layout will not change
size when an error is displayed.
Well based on this, try setting setErrorEnabled(true) before setError(), and, set setErrorEnabled(false) after setError(null).
Method setErrorEnabled(false) will clear the extra space, so call it after setError(null).
Dont use setErrorEnabled(boolean), it just doesnt show up the error from the second time.
public class MyTextInputLayout extends android.support.design.widget.TextInputLayout {
public MyTextInputLayout(Context context) {
super(context);
}
public MyTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setError(#Nullable CharSequence error) {
super.setError(error);
View layout = getChildAt(1);
if (layout != null) {
if (error != null && !"".equals(error.toString().trim())) {
layout.setVisibility(VISIBLE);
} else {
layout.setVisibility(GONE);
}
}
}
}
Then just setError(errorMessage); or setError(null);
See this page. Google will release the fix in future support library version. It says,
If you want to fix it now you can extends the TextInputLayout and
override the setErrorEnabled() method, but I cant guarantee the
backward compatibility. Because its some danger to change state in
TextInputLayout.
public class TextInputLayout extends android.support.design.widget.TextInputLayout{
public TextInputLayout(Context context) {
super(context);
}
public TextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setErrorEnabled(boolean enabled) {
super.setErrorEnabled(enabled);
if (enabled) {
return;
}
if (getChildCount() > 1) {
View view = getChildAt(1);
if (view != null) {
view.setVisibility(View.GONE);
}
}
}
}
I create a custom view for avoiding repeated code and override setError method.
public class UserInputView extends TextInputLayout {
public UserInputView(Context context) {
this(context, null);
}
public UserInputView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public UserInputView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setError(#Nullable CharSequence error) {
boolean isErrorEnabled = error != null;
setErrorEnabled(isErrorEnabled);
super.setError(error);
}
}
The source code of TextInputLayout show the following:
If you need to clear the error, just use
til.setErrorEnabled(false);
This will hide the error text and stretch the bottom space to its standard size.
In case you need to set the error again, just use
til.setError("Your text");
which automatically calls til.setErrorEnabled(true) as it assumes you need the error functionality.
This is extension in kotlin solving problem:
fun TextInputLayout.clearError() {
error = null
isErrorEnabled = false
}
The following code works fine
textInputLatout.getEditText().addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() < 1) {
textInputLayout.setErrorEnabled(true);
textInputLayout.setError("Please enter a value");
}
if (s.length() > 0) {
textInputLayout.setError(null);
textInputLayout.setErrorEnabled(false);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
By using mTextInputLayout.setErrorEnabled(false); i have solved this problem
Then you should override it like so:
#Override
public void onAnimationEnd(View view)
{
view.setVisibility(GONE); // <-- this is where you make it GONE
updateLabelVisibility(true);
}
Or try this i.e. on a button or whatever you are using:
final Button btn = (Button) findViewById(R.id.btn);
btn.setVisibility(View.GONE); //<--- makes the button gone
I'm trying to make a popup menu appear when the user clicks on an EditText but I don't want the EditText itself to be editable. I've tried many things like setting its KeyListener to null, setting it's InputType to null, but what always happens is that the first click gives the View focus and the second click actually registers with my OnClickListener. So user has to click twice to get the menu to popup. Any ideas?
public class PopupEditText extends EditText implements OnClickListener
{
private PopupMenu mMenu;
private Context mContext;
public PopupEditText(Context context)
{
super(context);
init(context);
}
public PopupEditText(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
public PopupEditText(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(context);
}
private void init(Context context)
{
mContext = context;
setKeyListener(null);
mMenu = new PopupMenu(context, this);
}
#Override
public void onClick(View view)
{
mMenu.show();
}
You're not far off. I'd recommend just overriding onTouchEvent() directly, and responding only to ACTION_UP events. Optionally, force it to be disabled and non-focusable. For example:
public class UnmodifiableEditText extends EditText {
private PopupMenu mPopupMenu;
public UnmodifiableEditText(Context context) {
super(context);
init(context);
}
public UnmodifiableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public UnmodifiableEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context ctx) {
super.setEnabled(false);
super.setFocusable(false);
mPopupMenu = new PopupMenu(ctx, this);
}
#Override public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Toast.makeText(getContext(), "Showing Popup", Toast.LENGTH_SHORT).show();
mPopupMenu.show();
}
return true;
}
#Override public void setEnabled(boolean enabled) {
// Do not allow enabling the EditText
}
#Override public void setFocusable(boolean focusable) {
// Do not allow focusability changes
}
}
in my application I have a flipView using the emilsjolander library. It's great, but I can't stop automatically the flipping effect when I open the FlipView. Infact, if I touch the screen the effect stop, but I would stop it after some seconds. Do you know if the library contain a method for it or, alternatively, for simulate the touchEvent after some seconds?
Thank's
I know the answer is so late but it will help others if they stuck in that issue. You can disable automatic flipping on first page by just commenting:
//peakNext(false);
public class MyFlipView extends se.emilsjolander.flipview.FlipView
{
private boolean isEnabled = true;
public MyFlipView(Context context)
{
super(context);
}
public MyFlipView(Context context, AttributeSet attrs)
{
super(context, attrs, 0);
}
public MyFlipView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (isEnabled)
return super.onInterceptTouchEvent(ev);
else
return false;
}
public void disable()
{
isEnabled = false;
}
public void enable()
{
isEnabled = true;
}
}
Declare xml as
<"YourPackage".MyFlipView
/>
how can I find out when onDraw of a View has finished?
Thanks!
I don't know what you're ultimately trying to achieve, but if you need to run some logic once drawing has been completed in an Activity, then you can call View.post(Runnable) and put your logic inside there. onDraw would have likely taken place once the code in your Runnable has been reached since it put that Runnable on the message queue.
Place a boolean member in your View class and set it to true when onDraw is called (If you simply want to be able to test that a View has drawn).
Or if you want some sort of post-draw "event" call to execute a new thread- just put it at the end of onDraw.
Another suggestion how it could be done:
public class FVRTraceAbleListView extends ListView {
ListViewListener listener;
public interface ListViewListener {
void onPostDraw();
}
public FVRTraceAbleListView(Context context) {
super(context);
}
public FVRTraceAbleListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FVRTraceAbleListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FVRTraceAbleListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setListener(ListViewListener listener) {
this.listener = listener;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (listener != null) {
listener.onPostDraw();
}
}
}