I need help on android Toast view as icon on error - java

My activity is a Video Player Activity and its working fine, On some Videos it must throw a message (handleHardwareAccelerationError) if the video is not supported or high quality.
It shows as Toast with message fine.
Now I would like to change this Toast message to show a picture or small icon instead, is this possible? Here is my code for handleHardwareAccelerationError, Thanks in advance.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
Toast.makeText(this, R.string.hardware_acceleration_error, Toast.LENGTH_LONG).show();
}
what I have tried is this but didnt show anything.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}
and here is myinforbar.xml
<LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="21dp" android:layout_marginLeft="0.0dip" android:layout_marginTop="5.0dip"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:src="#drawable/everyone_icon_nearby_cur"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:visibility="invisible"/>
</LinearLayout>
EDITED:
The original activity is long and it can be found here rather then pasting the whole activity you can see it here VideoPlayerActivity
( private void handleHardwareAccelerationError)
New Update...
This is without the message (onHardwareError) applied, I want to see icon inside this bottom little box that popup when video playing (infobar) instead of Toast message.

Toast is farily limited, you cannot show icons.
Edit: Gunjav Dave says it's possible, so it's approach worth a try.
Anyway this free library: SuperToast
can make what you need.
If you prefer to stick to Google's standards you can use, instead, the Snackbars, that don't allow, as far as I know, to put an icon, but can anyway be associated with an action/button, and they are standard.
I can't understand what you try to do with popupView, if you want to use a PopupWindow you have to use a completely different syntax. This Balloon Popup library of mine helps you to make a popup attached to a View, using a PopupWindow, you can also inflate into it a layout, or use it as an example on how to make a PopupWindow.
Edit:
You are inflating a layout inside a view, but this doesn't show the view. Instead, you should use a PopupWindow, and inflate inside it a layout.
This is an example taken from my BalloonPopup library:
// ....
hostedView = ((LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(layoutRes, null);
textView = (TextView) hostedView.findViewById(R.id.text_view);
textView.setText(text);
// ....
popupWindow = new PopupWindow(hostedView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
In other words, you should be able to do something like
PopupWindow popupWindow = new popupWindow(mError, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
in your code to show the popup window.
These are the essential points of the code, then you can reposition the popup, and eventually keep track of it to edit and re-show it instead of always creating from scratch. Please consider, anyway, to use BalloonPopup library, that does what you need, without getting crazy with animations, display times, window's permanence and positioning. You can just inflate into it your layout, for example with an icon and a text, and make it appear exactly on the center of another View, that can be your (already present) media player.
More edit:
Another very simple solution.
To get it simple, create a RelativeLayout, that hosts all your video player, and then create a simple ImageView in the center of it. Set its visibility to GONE when hidden and to VISIBLE when the error must be shown. Subsequently, you can use a timer or a touchListener to close it making it GONE again.

Try this
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
PopupWindow pw = new PopupWindow(popupView , 300, 400, true);
pw.showAtLocation(popupView , Gravity.CENTER, 0, 0);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}

XML Name or Layout Name would be
<LinearLayout xmlns:androidclass="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
Put This in Class:
LayoutInflater inflater = LayoutInflater.from(this);
View layout= inflater.inflate(R.layout.myinforbar, null);
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setView(layout);
toast.show();

Related

Google Ads interrupt the app. Slow down fps

I use AdView mAdView and the last updated libraries.
I placed the AdView into my layout (as shown in the examples):
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
ads:adSize="BANNER"
ads:adUnitId="#string/banner_ad_unit_id">
</com.google.android.gms.ads.AdView>
Then I identify it and try to load a new ad in the onCreate() method:
AdView mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
But my layout has some animated objects. This animation is freezing (skipping some frames) while new ad is become visible.
We can't catch the same problem with the disabled Internet (it disables ads and not affect lags).
I'm trying to show the problem with my own record (GIF can't show that completely):
https://www.youtube.com/watch?v=adH2Mn79O7w
How can I remove ads' lags and make the user experience better?
This is a known issue, which has been discussed many times on the net, is enough to search by the words "AdMob fps drop" and the like.
The root of the problem here, most likely, is that running AdMob requires significant resources, which is why the animation starts to stall. As one solution, you can show ads with some delay:
Handler handler = new Handler ();
handler.postDelayed (new Runnable () {
     #Override
     public void run () {
          AdRequest bannerRequest = new AdRequest.Builder (). Build ();
          mAdView.loadAd (bannerRequest);
     }
}, 2000);
You can make the delay not fixed, but bind it to user actions. For example, start downloading ads the moment after the user has stopped scrolling the screen.
Another solution is to disable graphics acceleration for ads by manipulating the LAYER_TYPE_SOFTWARE property.
mAdView.setAdListener(new AdListener(){
    #Override
    public void onAdLoaded(){
        runOnWebView(mAdView, new WebViewAction(){
            #Override
            public void run(WebView view){
                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }
        });
    }
});
For such a solution, it is necessary to implement the following interface:
private void runOnWebView (View view, WebViewAction action) {
    if (view instanceof WebView){
        action.run((WebView)view);
        return;
    }
    if (view instanceof ViewGroup) {
        final ViewGroup parent = (ViewGroup)view;
        for (int i = 0; i < parent.getChildCount(); i++) {
            runOnWebView(parent.getChildAt(i), action);
        }
    }
}
private interface WebViewAction{
    void run(WebView view);
}
Similarly, you can turn off the acceleration for some Activity:
<activity
android:hardwareAccelerated = "false"
android:softwareAccelerated = "false" />
As a workaround which I also have in my apps is setting a layertype:
mAdView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
or
mAdView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
I'd think, that the advertisments shouldn't be a banner, since that is a big advertisment, and that is slowing down the performance, as you should make it small. This also could cover things in your application, (if the advertisment is on banner).
Another thing is that you could not have ads, so that performance would be better. Try any of these. Ads most of the time have very good graphics and may slow down your application. :)
Place the ad view in a linear layout and implement ad listeners. In onAdLoaded() method of adListener add adView to your linear layout like linearLayout.addView(adView) and put your animation on linear layout. I hope it helps you.

How click to part of string of TextView in InputTextLayout (error or help message)

It's a solved problem, but I want to share my solution with community.
I use a component TextInputLayout with EditText inside.
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/textInputLayout"
style="#style/Widget.MaterialComponents.TextInputLayout.FilledBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/emailEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"/>
</com.google.android.material.textfield.TextInputLayout>
When I need to show error I use this method:
textInputLayout.setErrorEnabled(true);
textInputLayout.setError(errorMessage);
But in my case I need to show a button in a message inside errorMessage with another color and clickable.
For example my message:
User with this email already exist. Sign in
I need a clickable, bold text style Sign in in this message.
I used SpannableStringBuilder, changed color and created listener, but click event didn't work. And I couldn'd use method
TextView.setMovementMethod(LinkMovementMethod.getInstance());
for TextInputLayout or TextInputEditText.
After many hours to be trying to solve this case I found a some way, which works for me. I got a TextView from TextInputLayout by this:
((TextView)((FrameLayout)((LinearLayout) til.getChildAt(1)).getChildAt(0)).getChildAt(0))
.setMovementMethod(LinkMovementMethod.getInstance());
All code for creating part of message clickable in InputTextLayout:
textInputLayout.setErrorEnabled(true);
String text = getString("User with this email already exist. Sign in");
SpannableStringBuilder ssBuilder = new SpannableStringBuilder(text);
int startPoint = text.indexOf("Sign in");
int endPoint = text.indexOf("Sign in") + String.valueOf("Sign in").length();
int flags = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
ssBuilder.setSpan(new ClickableSpan() {
#Override
public void onClick(#NonNull View widget) {
//put your code here...
widget.invalidate(); //for hide background shadow after click
}
#Override
public void updateDrawState(#NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setFakeBoldText(true);
ds.setColor(getResources().getColor(R.color.colorWhite));
}
}, startPoint, endPoint, flags);
((TextView)((FrameLayout)((LinearLayout) textInputLayout.getChildAt(1)).getChildAt(0)).getChildAt(0))
.setMovementMethod(LinkMovementMethod.getInstance());
textInputLayout.setError(ssBuilder);
Thank you for your attention!
I think you should try creating a Material button button below
TextInputLayout with visibility set to hide as this will be an
easier solution instead of above solution that you have provided.
Whenever you want to show error as well as you can handle click on that button.

Display images through array in Android Studio

I'm trying to re-rig a quiz app to instead of displaying text questions, will display images (Ishihara slides to be specific).
For reference, here's a screenshot of the original quiz app:
When a user selects the true or false buttons, a toast appears with the result. Straightforward, and the previous/next buttons cycle through the questions. The questions are being stored as such:
final QuestionAndAnswer[] mQandA = new QuestionAndAnswer[]{
/*1*/ new QuestionAndAnswer(R.string.question_northAmerica, true),
/*2*/ new QuestionAndAnswer(R.string.question_antarctica, false),
/*3*/ new QuestionAndAnswer(R.string.question_canada, false),
/*4*/ new QuestionAndAnswer(R.string.question_madagascar, true),
/*5*/ new QuestionAndAnswer(R.string.question_wonders, false)
};
I thought that pointing the new QuestionAndAnswer at R.drawable.imagename could accomplish this, but instead just displays the image's location as text.
And changing it to new ImageView(R.drawable.imagename, true) throws the error:
ImageView (android.content.Context, android.util.AttributeSet)in ImageView cannot be applied to (int,boolean)
I'm sorry, I'm still very new to Android but as you've probably put together by now, I'm a student and don't have a choice but to do this.
If you have something like this on layout xml
<RelativeLayout ...
...
<TextView android:id="#+id/text_view_id" ... />
...
</RelativeLayout>
You need to change it to
<RelativeLayout ...
...
<ImageView android:id="#+id/image_view_id" ... />
...
</RelativeLayout>
Then on your activity class, maybe you have something like below
TextView textView;
public void onCreate() {
textView = (TextView) findViewById(R.id.text_view_id);
....
textView.setText(mQandA[i].question)
}
Where mQandA[i].question is your question resource a.k.a R.string.question_northAmerica
Change it to
ImageView imageView;
public void onCreate() {
imageView = (ImageView) findViewById(R.id.image_view_id);
...
imageView.setImageResource(mQandA[i].question)
}
Where mQandA[i].question is your image resource a.k.a R.drawable.imagename
EDIT 1
change every appearance of
textView.setText(mQandA[i].question)
with
imageView.setImageResource(mQandA[i].question)
counterpart

addView adds the view but it's not showing it

I know this has already been asked, but I tried everything and I couldn't solve my problem.
When I create the views programmatically, they are definitely added. I checked in the debugger and everything is in it's place, even the parent view gets bigger in height because they are using space. But I can't see them. It's like they are below other views or invisible (but they are not. I checked many times...).
This is the xml code where I'm trying to insert the views. I want to insert them where the cursor is (where it's tagged information). I only have it there to show you how it will look like in the end, but this part will be added programmatically.
<LinearLayout
android:id="#+id/llhTestItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:orientation="horizontal">
<TextView
android:id="#+id/tvInformationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="17sp"
fontPath="fonts/OpenSans-Regular.ttf"
android:text="Sub title: "/> <!-- tvInformationTitle -->
<TextView
android:id="#+id/tvInformation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
fontPath="fonts/OpenSans-Light.ttf"
android:text="information"/> <!-- tvInformation -->
</LinearLayout> <!-- information -->
Below you can see the code that I'm using to add the views just like in the xml above.
#Override
public void onBindViewHolder(SetupViewerHolder holder, int position) {
CardViewItem cardViewItem = cardViewItemList.get(position);
holder.tvTitle.setText(cardViewItem.getCardTitle());
for (int i = 0; i < cardViewItem.getInformationList().size(); i++){
//region Create llhItem
LinearLayout.LayoutParams llhItemParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
llhItemParams.topMargin = dipToPixels(6);
LinearLayout llhItem = new LinearLayout(context);
llhItem.setLayoutParams(llhItemParams);
llhItem.setOrientation(LinearLayout.HORIZONTAL);
//endregion
LinearLayout.LayoutParams tvInformationsParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//region Create tvInformationTitle
TextView tvInformationTitle = new TextView(context);
tvInformationTitle.setLayoutParams(tvInformationsParams);
tvInformationTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
if (Build.VERSION.SDK_INT < 23){
tvInformationTitle.setTextAppearance(context, R.style.OpenSansRegular);
} else {
tvInformationTitle.setTextAppearance(R.style.OpenSansRegular);
}
tvInformationTitle.setText(cardViewItem.getInformationList().get(i)[0]);
//endregion
//region Create tvInformation
TextView tvInformation = new TextView(context);
tvInformation.setLayoutParams(tvInformationsParams);
tvInformation.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
if (Build.VERSION.SDK_INT < 23){
tvInformation.setTextAppearance(context, R.style.OpenSansLight);
} else {
tvInformation.setTextAppearance(R.style.OpenSansLight);
}
tvInformation.setText(cardViewItem.getInformationList().get(i)[1]);
//endregion
llhItem.addView(tvInformationTitle);
llhItem.addView(tvInformation);
holder.llvInformation.addView(llhItem);
}
Basically what I'm trying to achieve is to have a recycler view, and each item has only one title, one overflow button, but can have multiple information rows.
Here is a print of this, which I had hard coded in xml previously as a prototype.
I know of some alternative ways of doing this that might work, but for now I would like to have it like this, since everything is working like it should, the views are just "not visible".
Had to use layout.post
holder.llvInformation.post( new Runnable() {
#Override
public void run() {
holder.llvInformation.addView(llhItem);
}
});
Have you tried calling invalidate() after adding the view? Like this:
holder.llvInformation.addView(llhItem);
holder.llvInformation.invalidate();

Android ImageButton swap resource leaves 'residue'

I have 2 Images:
IMG_1:
IMG_1_PRESSED:
I display IMG_1 by default, but when I click on it, the image should change to IMG_1_PRESSED.
Here's a code snippet of the button itself, where be is an enum containing the correct drawables:
ImageButton ib = new ImageButton(this.context);
ib.setImageResource(be.getDrawable());
ib.setScaleType(ImageButton.ScaleType.CENTER_INSIDE);
ib.setBackgroundColor(Color.TRANSPARENT);
ib.setPadding(0, 0, 0, 0);
ib.setAdjustViewBounds(true);
ib.setMaxWidth(width);
ib.setMaxHeight(height);
setStrengthListener(ib, be);
And here is the setStrengthListener method:
private void setStrengthListener(final ImageButton ib, final ButtonEnum be){
ib.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
ib.setImageResource(be.getDrawablePressed());
return true;
case MotionEvent.ACTION_UP:
ib.setImageResource(be.getDrawable());
return true;
}
return false;
}
});
}
Now both images are 480x240 and width and height are set to device's width/3 and device's width/6 respectively (I want to display 3 images, hence the /3).
Here's the problem, if the button is pressed, I get this:
There's this little line under the pressed button... I've tried a lot to fix this but somehow that little line has made itself my greatest enemy today.
As an extra effort: the line doesn't show anymore if I set the original resource to IMG_1_PRESSED:
ImageButton ib = new ImageButton(this.context);
ib.setImageResource(be.getDrawablePressed());
ib.setScaleType(ImageButton.ScaleType.CENTER_INSIDE);
ib.setBackgroundColor(Color.TRANSPARENT);
ib.setPadding(0, 0, 0, 0);
....etc
But obviously I don't want to start with a pressed button.
So dear Android experts, what am I doing wrong here?
This is the simplest solution as i know,
Try this
create Xml inside your Drawable folder
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_pressed_img"android:state_pressed="true" />
<item android:drawable="#drawable/btn_normal_image" />
</selector>
Then add this drawable file as background to your View
Example :
<ImageView
android:id="#+id/enter_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:maxHeight="100dip"
android:maxWidth="100dip"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:background="#drawable/enter_btn" />
or in Java code
yourView.setImageResource(R.drawable.*drawablefile*);
You can use ImageButton also but ImageView would look better than ImageButton since it doesn't have button borders.
So after a hell of a lot of trial and error, I managed to get that grey line away. In the end it was very simple really, though I'm not completely sure why this fixed it:
The main layout:
LinearLayout ll = new LinearLayout(this);
ll.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setGravity(Gravity.TOP);
The view creation (layout for imageview is unchanged):
ImageView iv = tbb.getTopBarButton(ButtonEnum.IMG_1);
LinearLayout iViewLayout = new LinearLayout(this);
iViewLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
iViewLayout.setOrientation(LinearLayout.HORIZONTAL);
iViewLayout.addView(iv);
ll.addView(iViewLayout);
Adding a separate layout per imageview seemed to remove the grey line. Would love to know WHY this works though, but for future reference, at least I hope to help others.

Categories

Resources