How to Implement UnifiedNative ads in Xamarin.Forms ios - xamarin.forms

I am trying to add UnifiedNative ads in my xamarin.forms Application. I successfully implemented them in Android but having a hard time for iOS.
For Android - I have created a custom renderer and a xml layout for holding the Ad content.
For ios, I tried to follow this - github.com/xamarin/GoogleApisForiOSComponents/blob/master/docs/Firebase/AdMob/ but it is not very clear and provides help only in Swift/Objective C and I am looking for C#.
EDIT -
Xamarin.Forms
in .xaml
<adview:AdmobNativeAd HeightRequest="360"></adview:AdmobNativeAd>
AdView class -
public class AdmobNativeAd : ContentView
{
public AdmobNativeAd()
{
this.HeightRequest = 360;
this.Margin = new Thickness(8, 8, 8, 0);
SetPlaceholderContent();
}
private void SetPlaceholderContent()
{
var placeholderGrid = new Grid();
var placeHolderText = new Label
{
Text = "AD",
FontSize = 48,
FontAttributes = FontAttributes.Bold,
TextColor = Color.White,
Opacity = 0.3,
VerticalOptions = new LayoutOptions(LayoutAlignment.Center, true),
HorizontalOptions = new LayoutOptions(LayoutAlignment.Center, true)
};
placeholderGrid.Children.Add(placeHolderText);
this.Content = placeholderGrid;
}
}
Android Implementation -
[assembly: ExportRenderer(typeof(AdmobNativeAd), typeof(xxx.Droid.Services.NativeAd))]
namespace xxx.Droid.Services
{
public class NativeAd : ViewRenderer
{
public NativeAd(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var adLoader = new AdLoader.Builder(Context, "ca-app-pub-xxxxxxxxxxx/xxxxxxxx");
var listener = new UnifiedNativeAdLoadedListener();
listener.OnNativeAdLoaded += (s, ad) =>
{
try
{
var root = new UnifiedNativeAdView(Context);
var inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
var adView = (UnifiedNativeAdView)inflater.Inflate(Resource.Layout.ad_unified, root);
populateUnifiedNativeAdView(ad, adView);
SetNativeControl(adView);
}
catch
{
}
};
adLoader.ForUnifiedNativeAd(listener);
var requestBuilder = new AdRequest.Builder();
adLoader.Build().LoadAd(requestBuilder.Build());
}
}
private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView)
{
adView.MediaView = adView.FindViewById<MediaView>(Resource.Id.ad_media);
// Set other ad assets.
adView.HeadlineView = adView.FindViewById<TextView>(Resource.Id.ad_headline);
adView.BodyView = adView.FindViewById<TextView>(Resource.Id.ad_body);
adView.CallToActionView = adView.FindViewById<TextView>(Resource.Id.ad_call_to_action);
adView.IconView = adView.FindViewById<ImageView>(Resource.Id.ad_app_icon);
adView.PriceView = adView.FindViewById<TextView>(Resource.Id.ad_price);
adView.StarRatingView = adView.FindViewById<RatingBar>(Resource.Id.ad_stars);
adView.StoreView = adView.FindViewById<TextView>(Resource.Id.ad_store);
adView.AdvertiserView = adView.FindViewById<TextView>(Resource.Id.ad_advertiser);
// The headline and mediaContent are guaranteed to be in every UnifiedNativeAd.
((TextView)adView.HeadlineView).Text = nativeAd.Headline;
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
if (nativeAd.Body == null)
{
adView.BodyView.Visibility = ViewStates.Invisible;
}
else
{
adView.BodyView.Visibility = ViewStates.Visible;
((TextView)adView.BodyView).Text = nativeAd.Body;
}
if (nativeAd.CallToAction == null)
{
adView.CallToActionView.Visibility = ViewStates.Invisible;
}
else
{
adView.CallToActionView.Visibility = ViewStates.Visible;
((Android.Widget.Button)adView.CallToActionView).Text = nativeAd.CallToAction;
}
if (nativeAd.Icon == null)
{
adView.IconView.Visibility = ViewStates.Gone;
}
else
{
((ImageView)adView.IconView).SetImageDrawable(nativeAd.Icon.Drawable);
adView.IconView.Visibility = ViewStates.Visible;
}
if (string.IsNullOrEmpty(nativeAd.Price))
{
adView.PriceView.Visibility = ViewStates.Gone;
}
else
{
adView.PriceView.Visibility = ViewStates.Visible;
((TextView)adView.PriceView).Text = nativeAd.Price;
}
if (nativeAd.Store == null)
{
adView.StoreView.Visibility = ViewStates.Invisible;
}
else
{
adView.StoreView.Visibility = ViewStates.Visible;
((TextView)adView.StoreView).Text = nativeAd.Store;
}
if (nativeAd.StarRating == null)
{
adView.StarRatingView.Visibility = ViewStates.Invisible;
}
else
{
((RatingBar)adView.StarRatingView).Rating = nativeAd.StarRating.FloatValue();
adView.StarRatingView.Visibility = ViewStates.Visible;
}
if (nativeAd.Advertiser == null)
{
adView.AdvertiserView.Visibility = ViewStates.Invisible;
}
else
{
((TextView)adView.AdvertiserView).Text = nativeAd.Advertiser;
adView.AdvertiserView.Visibility = ViewStates.Visible;
}
// This method tells the Google Mobile Ads SDK that you have finished populating your
// native ad view with this native ad.
adView.SetNativeAd(nativeAd);
}
}
public class UnifiedNativeAdLoadedListener : AdListener, UnifiedNativeAd.IOnUnifiedNativeAdLoadedListener
{
public void OnUnifiedNativeAdLoaded(UnifiedNativeAd ad)
{
OnNativeAdLoaded?.Invoke(this, ad);
}
public EventHandler<UnifiedNativeAd> OnNativeAdLoaded { get; set; }
}
}
XML to handle received Ad Content -
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.formats.UnifiedNativeAdView android:hardwareAccelerated="false"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardPreventCornerOverlap="false"
app:cardCornerRadius="12dp">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FFFFFF">
<AbsoluteLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<com.google.android.gms.ads.formats.MediaView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ad_media"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="Ad"
android:textColor="#FFFFFF"
android:background="#FFCC66"
android:textSize="14sp"
android:padding="4dp" />
</AbsoluteLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="fill_horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/ad_app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:paddingBottom="5dp"
android:paddingEnd="5dp"
android:paddingRight="5dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#0000FF"
android:text="Join the dark side!"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:textSize="14sp"
android:text="Google"
android:textColor="#222222"
android:textStyle="bold"/>
<RatingBar
android:id="#+id/ad_stars"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5"
android:rating="4" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:textColor="#555555"
android:id="#+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nis."
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:paddingLeft="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="#+id/ad_store"
android:text="Google Play"
android:textColor="#222222"
android:textSize="12sp" />
<Button
android:id="#+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="0dp"
android:text="INSTALL"
android:textSize="12sp" />
<TextView
android:id="#+id/ad_price"
android:text="$ 3.49"
android:textColor="#222222"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</com.google.android.gms.ads.formats.UnifiedNativeAdView>
I have referred this article for Android Implmentation -
https://startdebugging.net/2019/09/admob-native-ads-in-xamarin-forms-android/
I tried this in IOS and my code so far is this -
[assembly: ExportRenderer(typeof(AdmobNativeAd), typeof(AdMobNativeAdRenderer))]
namespace xxxx.iOS.Renderers
{
public class AdMobNativeAdRenderer : ViewRenderer<AdmobNativeAd, NativeExpressAdView>
{
NativeExpressAdView mAdView;
bool viewOnScreen;
// public AdMobNativeAdRenderer(Context context) : base() { }
protected override void OnElementChanged(ElementChangedEventArgs<AdmobNativeAd> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (e.OldElement == null)
{
CreateAdView(this);
}
}
private void CreateAdView(AdMobNativeAdRenderer renderer)
{
if (Element == null) return;
var loader = new AdLoader(
"ca-app-pub-xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxx",
GetVisibleViewController(),
new AdLoaderAdType[] { AdLoaderAdType.UnifiedNative },
new AdLoaderOptions[] {
new NativeAdViewAdOptions {PreferredAdChoicesPosition = AdChoicesPosition.TopRightCorner}
});
var request = Request.GetDefaultRequest();
request.TestDevices = new string[] { Request.SimulatorId };
if (adView == null) return;
try
{
loader.Delegate = new MyAdLoaderDelegate(renderer);
loader.LoadRequest(request);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
Debug.WriteLine("Loading: " + loader.IsLoading);
}
private UIViewController GetVisibleViewController()
{
var windows = UIApplication.SharedApplication.Windows;
foreach (var window in windows)
{
if (window.RootViewController != null)
{
return window.RootViewController;
}
}
return null;
}
I couldn't figure out how to create UI similar to xml doc above for IOS and link it with the delegate.
Also, I would like to mention I am using Visual studio 2019 Windows for this project.

Related

How to interact between adapt and fragment?

I thank you in advance for your help. I am not a professional developer. I'm a teacher. I'm looking to create an app that can time student performance. I want to start a general stopwatch and stop the stopwatch individually. But, I encounter a problem either I don't have a crash but I can't interact on the individual stop button or I have a crash of type "binding.btnStop make not null"
Can you tell me how I can interact between the adapter and the fragment to link the general and individual timers and to stop the individual timer?
Thank you in advance for your help
Here is my code:
EvalFragment.class
var mDisplay: Display? = null
var path: String? = null
val REQUEST_CODE = 1
var isPlay = false
var pauseOffSet :Long = 0
//Test chrono millisec
var isResume = false
private lateinit var handler: Handler
var tMilliSec = 0L
var tStart = 0L
var tBuff = 0L
var tUpdate = 0L
var sec: Int = 0
var min: Int = 0
var milliSec: Int = 0
//Pour accéder au fab
private var _binding: FragmentEvalBinding? = null
private val binding get() = _binding!!
private lateinit var mUserViewModel: UserViewModel
private lateinit var mUserEvalViewModel: UserEvalViewModel
private val args by navArgs<EvalFragmentArgs>()
private lateinit var btPlay: ImageButton
private lateinit var btnPause: ImageButton
private lateinit var btStop: ImageButton
private lateinit var chronomter: Chronometer
#RequiresApi(Build.VERSION_CODES.R)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentEvalBinding.inflate(inflater, container, false)
val view = binding.root
//Recyclerview pour afficher le custom row et les données
val adapter = EvalAdapter()
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerview_time)
recyclerView?.adapter = adapter
recyclerView?.layoutManager = LinearLayoutManager(requireContext())
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mUserEvalViewModel = ViewModelProvider(this).get(UserEvalViewModel::class.java)
chronomter = binding.chronometerGeneral
btPlay = binding.btStart
btStop = binding.btStop
btnPause = binding.btPause
handler = Handler()
btPlay.setOnClickListener {
if(!isResume){
tStart = SystemClock.uptimeMillis()
handler.postDelayed(runnable, 0)
chronomter.start()
binding.recyclerviewTime.chronometerIndividuel.start()
isResume = true
btStop.visibility = View.GONE
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_pause))
} else {
tBuff += tMilliSec
handler.removeCallbacks(runnable)
chronomter.stop()
binding.recyclerviewTime.chronometerIndividuel.stop()
isResume = false
btStop.visibility = View.VISIBLE
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_play))
}
}
btnPause.setOnClickListener {
pause()
}
btStop.setOnClickListener {
stop()
if(!isResume){
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_play))
tMilliSec = 0L
tStart = 0L
tBuff = 0L
tUpdate = 0L
sec = 0
min = 0
milliSec = 0
chronomter.setText("00:00:00")
binding.recyclerviewTime.chronometerIndividuel.setText("00:00:00")
}
}
val userStart = args.currentUser.time
mUserEvalViewModel.readAllDataUserEval?.observe(viewLifecycleOwner, Observer { user ->
adapter.setDataEval(user)
})
val wm: WindowManager? =
activity?.getSystemService(Context.WINDOW_SERVICE) as WindowManager?
mDisplay = wm!!.defaultDisplay
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
), REQUEST_CODE
)
} else {
Toast.makeText(
requireContext(),
"Veuillez accepter les permissions",
Toast.LENGTH_SHORT
).show()
}
// Add menu
setHasOptionsMenu(true)
return view
}
val runnable: Runnable = object : Runnable {
override fun run() {
tMilliSec = SystemClock.uptimeMillis() - tStart
tUpdate = tBuff + tMilliSec
sec = (tUpdate/1000).toInt()
min= sec/60
sec = sec%60
milliSec = (tUpdate%100).toInt()
chronomter.setText(String.format("%02d", min)+":"
+ String.format("%02d", sec)+":"+String.format("%02d", milliSec))
handler.postDelayed(this, 60)
}
}
private fun clicSound() {
val mediaPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.positive_notification)
mediaPlayer.start()
}
private fun pause() {
if (isPlay){
chronomter.stop()
pauseOffSet = SystemClock.elapsedRealtime() - chronomter.base
isPlay = false
btnPause.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context,"Chronomètre: en Pause !!",Toast.LENGTH_SHORT).show()
}
else{
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.start()
btnPause.setBackgroundResource(R.drawable.ic_pause)
Toast.makeText(context,"Chronomètre : en route !!",Toast.LENGTH_SHORT).show()
isPlay = true
}
}
private fun play() {
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.start()
btPlay.setBackgroundResource(R.drawable.ic_stop)
Toast.makeText(context,"Chronomètre déclenché !!",Toast.LENGTH_SHORT).show()
isPlay =true
}
private fun stop() {
chronomter.base = SystemClock.elapsedRealtime()
pauseOffSet = 0
chronomter.stop()
btPlay.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context, "Chronomètre arrêté !!", Toast.LENGTH_SHORT).show()
isPlay = false
}
private fun reset(){
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.stop()
btnPause.visibility = View.INVISIBLE
btPlay.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context,"Chronomter is Start !!",Toast.LENGTH_SHORT).show()
isPlay = false
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PackageManager.PERMISSION_GRANTED && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(requireContext(), "Permission Autorisée", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(requireContext(), "Permission Refusée", Toast.LENGTH_SHORT).show()
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.delete_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_delete) {
// deleteAllEvals()
}
return super.onOptionsItemSelected(item)
}
}```
My EvalAdapter.class:
```class EvalAdapter: RecyclerView.Adapter<EvalAdapter.MyViewHolder>() {
var evalList = emptyList<UserWithEval>()
private lateinit var mUserViewModel: UserViewModel
private lateinit var mEvalViewModel: EvalViewModel
private lateinit var mUserWithEvalViewModel: UserEvalViewModel
private lateinit var firstName: String
private lateinit var lastName: String
private var idUser: Int = 0
private var user_id_reference: Int = 0
private var gru_id_reference: Int = 0
private var timeInterDepart = 0
private lateinit var chronoInd : Chronometer
private lateinit var chronoGeneral : Chronometer
private lateinit var context: Context
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
context = parent.context
return MyViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.custom_time, parent, false)
)
}
override fun getItemCount(): Int {
return evalList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItemUser = evalList[position]
holder.itemView.findViewById<TextView>(R.id.firstName_txt).text = currentItemUser.firstName.uppercase()
holder.itemView.findViewById<TextView>(R.id.lastName_txt).text = currentItemUser.lastName.uppercase()
chronoInd = holder.itemView.findViewById(R.id.chronometerIndividuel)
holder.itemView.findViewById<Button>(R.id.bt_stop_individuel).setOnClickListener {
chronoInd.stop()
}
}
fun setDataEval(user: List<UserWithEval>){
this.evalList = user
notifyDataSetChanged()
}
}```
fragment_eval.xml:
```<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#drawable/gradient_background"
android:orientation="horizontal"
android:id="#+id/fragEval">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview_time"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/linearLayoutCompat"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_margin="30dp"
android:background="#drawable/bg_round"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Chronometer
android:id="#+id/chronometerGeneral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:format="00:00:00"
android:textColor="#color/white"
android:textSize="40sp"
android:textStyle="bold" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<ImageButton
android:id="#+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_play" />
<ImageButton
android:id="#+id/bt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_stop" />
<ImageButton
android:id="#+id/bt_pause"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_pause" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<EditText
android:id="#+id/editTextTempsDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/custom_input_eval"
android:drawableLeft="#drawable/ic_chrono"
android:hint=" 15 "
android:inputType="number"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="#+id/linearLayoutCompat"
app:layout_constraintEnd_toStartOf="#+id/linearLayoutCompat"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/validTempsDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/validate"
android:layout_marginLeft="20dp"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/editTextTempsDepart"
app:layout_constraintStart_toEndOf="#+id/editTextTempsDepart"
app:layout_constraintTop_toTopOf="#+id/editTextTempsDepart" />
<TextView
android:id="#+id/tvTempsPremierDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/custom_input"
android:text="00 sec"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/linearLayoutCompat"
app:layout_constraintTop_toBottomOf="#+id/linearLayoutCompat" />
</androidx.constraintlayout.widget.ConstraintLayout>
custom_time.xml:
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#drawable/gradient_background"
tools:context=".MainActivity">
//1ère ligne du chrono
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/bt_stop_individuel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/shape_background"
android:text="#string/stop"
android:textColor="#color/white"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:id="#+id/firstName_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="#string/firstName"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="#+id/lastName_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="#string/lastName"
android:textSize="25sp"
android:textStyle="bold" />
<Chronometer
android:id="#+id/chronometerIndividuel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:format="00:00:00"
android:text="00:00:00"
android:textSize="30sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Image capture and upload inside a fragment in kotlin

THIS IS MY XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MakeComplaint.Category_Description"
android:background="#drawable/fragmentgradient_bg">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/heading_constraint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:layout_editor_absoluteX="17dp">
<ImageView
android:id="#+id/backToHistory"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingHorizontal="20dp"
android:layout_weight="2"
android:src="#drawable/ic_backarrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="#+id/location_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/location_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingHorizontal="20dp"
android:fontFamily="#font/pathway_gothic_one"
android:gravity="center"
android:textSize="40sp"
android:text="Further Details"
app:layout_constraintHorizontal_bias="0.35"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#+id/backToHistory"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.cardview.widget.CardView
android:id="#+id/details_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:elevation="#dimen/card_spacing"
app:cardUseCompatPadding="true"
app:layout_constraintTop_toBottomOf="#+id/heading_constraint"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:cardCornerRadius="#dimen/card_spacing"
>
<ScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/inner_constraint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/card_spacing">
<TextView
android:id="#+id/guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/pathway_gothic_one"
android:gravity="left"
android:text="Please enter any further details you would like to add:"
android:textSize="20sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/description_text_input"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:boxStrokeColor="#color/teal"
app:boxStrokeWidth="#dimen/card_spacing"
app:counterEnabled="true"
app:counterMaxLength="500"
android:hint="Additional Notes"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/guide"
app:prefixTextColor="#color/colorPrimaryDark"
android:outlineAmbientShadowColor="#color/teal"
android:outlineSpotShadowColor="#color/teal"
android:scrollbarAlwaysDrawHorizontalTrack="true"
app:layout_constraintBaseline_creator="#android:integer/config_longAnimTime"
>
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences|textMultiLine"
android:maxLength="500"
/>
</com.google.android.material.textfield.TextInputLayout>
<!--ImageView where image will be set-->
<ImageView
android:id="#+id/display_image"
android:scaleType="centerCrop"
android:layout_width="250dp"
android:layout_height="250dp"
android:adjustViewBounds="true"
app:layout_constraintTop_toBottomOf="#+id/description_text_input"
app:layout_constraintBottom_toTopOf="#+id/FAB_buttons"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/FAB_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/description_text_input"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginVertical="5dp">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:backgroundTint="#color/teal"
android:layout_marginHorizontal="#dimen/card_spacing"
android:src="#android:drawable/ic_menu_camera"
app:layout_constraintRight_toLeftOf="#+id/camera"
app:layout_constraintTop_toBottomOf="#+id/name_text_input"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:backgroundTint="#color/teal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/name_text_input"
android:src="#android:drawable/ic_menu_gallery"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Make Complaint"
app:layout_constraintTop_toBottomOf="#+id/FAB_buttons"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:backgroundTint="#color/teal"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>```
**THIS IS MY KOTLIN FILE**
package com.example.atry.MakeComplaint
class Category_Description : Fragment() {
private val ALL_PERMISSIONS_RESULT = 107
private val IMAGE_RESULT = 200
private val REQUEST_IMAGE_CAPTURE = 12345
var mBitmap: Bitmap? = null
val permission = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(com.example.atry.R.layout.fragment_category__description, container, false)
val camera_FAB: View = v.findViewById(com.example.atry.R.id.camera)
val upload_FAB: View = v.findViewById(com.example.atry.R.id.upload)
val imageView = v.findViewById<ImageView>(com.example.atry.R.id.display_image)
upload_FAB.setOnClickListener {
pickImageFromGallery()
}
camera_FAB.setOnClickListener{
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val frag = this
/** Pass your fragment reference **/
frag.startActivityForResult(
intent,
REQUEST_IMAGE_CAPTURE
) // REQUEST_IMAGE_CAPTURE = 12345
}
fun hasPermissionInManifest(context: Context, permissionName: String): Boolean {
val packageName = context.packageName
try {
val packageInfo = context.packageManager
.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
val declaredPermisisons = packageInfo.requestedPermissions
if (declaredPermisisons != null && declaredPermisisons.size > 0) {
for (p in declaredPermisisons) {
if (p == permissionName) {
return true
}
}
}
} catch (e: PackageManager.NameNotFoundException) {
}
return false
}
v.backToHistory.setOnClickListener {
backFragment()
}
// Inflate the layout for this fragment
return v
}
private fun pickImageFromGallery() {
//Intent to pick image
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, IMAGE_PICK_CODE)
}
companion object {
//image pick code
private val IMAGE_PICK_CODE = 1000;
//Permission code
private val PERMISSION_CODE = 1001;
}
private fun backFragment() {
val manager = (context as AppCompatActivity).supportFragmentManager
manager.popBackStackImmediate()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data !=null) {
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode== IMAGE_PICK_CODE) {
// Do something with imagePath
val extras = data.getExtras()
val photo = extras.get("data") as Bitmap
val imageView = view!!.findViewById<ImageView>(com.example.atry.R.id.display_image)
imageView.setImageBitmap(photo)
// CALL THIS METHOD TO GET THE URI FROM THE BITMAP
var selectedImage = activity.let { getImageUri( it!!,photo) }
val realPath = selectedImage.let { getRealPathFromURI(it) }
selectedImage = Uri.parse(realPath)
}
}
super.onActivityResult(requestCode, resultCode, data)
}
fun getImageUri(inContext: Context, inImage: Bitmap): Uri {
val bytes = ByteArrayOutputStream()
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
val path =
MediaStore.Images.Media.insertImage(inContext.contentResolver, inImage, "Title", null)
return Uri.parse(path)
}
fun getRealPathFromURI(contentUri: Uri): String {
var cursor: Cursor? = null
try {
val proj = arrayOf(MediaStore.Images.Media.DATA)
cursor = getActivity()?.getContentResolver()?.query(contentUri, proj, null, null, null)
val column_index = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor!!.moveToFirst()
return cursor!!.getString(column_index)
} finally {
if (cursor != null) {
cursor!!.close()
}
}
}
}```
For capturing the image everything works fine until the screen appears where I click on the tick to approve that the picture is okay...but then I am unable to view anything on the ImageView.
For the upload button when I am on the screen that allows me to select the picture ...when i click on it the app crashes and gives me the following error: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.os.Bundle.get(java.lang.String)' on a null object reference
I have searched the internet for days and couldn't find a proper solution to this. I would appreciate it if anyone could find me a solution to this.
URI of the selected image is not returned in Intent extras, but in the data of intent. You can get the selected image's URI as follows.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data !=null) {
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode== IMAGE_PICK_CODE) {
// Get image URI From intent
var imageUri = data.data
// do something with the image URI
your_image_view.setImageURI(imageUri)
}
}
super.onActivityResult(requestCode, resultCode, data)
}

Xamarin Android (PCL) Layout not correctly render in dependency service

I am trying to display a dialog on Android using Dependency Service. However, I could not get the design I create in android layout designer to display, the result comes out is different.
This is the screenshot of my previewer:
Expected design
This is the screenshot of my result:
Unexpected result
My axml code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/dialogWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:background="#drawable/backgroundstyle"
android:layout_marginRight="16dp"
android:stateListAnimator="#null">
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="16dp"
android:textAlignment="center"
android:textColor="#000"
android:textSize="19sp"
android:text="TitleText"
android:textStyle="bold" />
<TextView
android:id="#+id/subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/title"
android:paddingBottom="16dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="4dp"
android:textAlignment="center"
android:text="subtitle test"
android:textColor="#000"
android:textSize="15sp" />
<RelativeLayout
android:id="#+id/RL_editTextWrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/subtitle"
android:padding="15dp"
>
<EditText
android:id="#+id/inputText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/roundedentry"
android:paddingBottom="8dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="8dp"
android:textAlignment="center"
android:textColor="#000"
android:text="inputText test"
android:textSize="15sp" />
</RelativeLayout>
<View
android:id="#+id/line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#+id/RL_editTextWrapper"
android:background="#cdced2" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/line"
android:orientation="horizontal">
<TextView
android:id="#+id/dialogButtonNO"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:stateListAnimator="#null"
android:textAlignment="center"
android:textColor="#007aff"
android:text="Cancel"
android:textSize="19sp" />
<View
android:id="#+id/separator"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#cdced2" />
<TextView
android:id="#+id/dialogButtonOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:stateListAnimator="#null"
android:textAlignment="center"
android:textColor="#007aff"
android:textSize="19sp"
android:text="Ok"
android:textStyle="bold" />
</LinearLayout>
The #drawable/backgroundstyle code:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#android:color/white"/>
<corners
android:radius="16dp" />
This is the code for exporting dependency service in android:
namespace FFF.Droid.Native {
public class IOSDialogStyleDroid : IIOSDialogStyle {
public void ShowPopup(EntryPopup entryPopup) {
var context = CrossCurrentActivity.Current.Activity as FormsAppCompatActivity;
CustomDialog customDialog = new CustomDialog(context) {
entryPopup = entryPopup
};
customDialog.Show();
}
}
public class CustomDialog : Dialog {
public Context context { get; set; }
public EntryPopup entryPopup { get; set; }
public CustomDialog(Context context) : base(context) {
this.context = context;
}
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
RequestWindowFeature((int)WindowFeatures.NoTitle);
SetContentView(Resource.Layout.iOSStyleDialog);
EditText editText = FindViewById(Resource.Id.inputText) as EditText;
(FindViewById(Resource.Id.title) as TextView).Text = entryPopup.Title;
(FindViewById(Resource.Id.subtitle) as TextView).Text = entryPopup.Message;
var btnOk = FindViewById(Resource.Id.dialogButtonOK) as TextView;
btnOk.Text = entryPopup.okButton;
btnOk.Click += (object sender, EventArgs e) => {
entryPopup.OnPopupClosed(new EntryPopupClosedArgs {
Button = entryPopup.okButton,
Text = editText.Text
});
Dismiss();
};
var btnNo = FindViewById(Resource.Id.dialogButtonNO) as TextView;
btnNo.Text = entryPopup.cancelButton;
btnNo.Click += (object sender, EventArgs e) => {
entryPopup.OnPopupClosed(new EntryPopupClosedArgs {
Button = entryPopup.cancelButton,
Text = editText.Text
});
Dismiss();
};
}
}
I found out that textalignment seems broken, I use gravity instead.

listview inside scrollview not working on android version lower than API 18

ListView inside ScrollView works perfectly on android API greater than 18 but, with lower than API 18 app crash showing java.lang.NullPointerException in line
listItem.measure(0, 0); on MyUtils.java
MyUtils.java
public static void setListViewHeightBasedOnChildren(ExpandableListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
fragment_list.xml
<FrameLayout 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"
tools:context="sportsnewsforcrazysportpepllatestnewsjstwaao.com.sportsnews.fragments.Frag_List">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/networkImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#color/divider"
android:minHeight="150dp"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/expandableListView"
android:scrollbars="none"
android:background="#color/app_background"
android:childDivider="#color/app_background"/>
</LinearLayout>
</ScrollView>
Fragment_list.java
adapter = new ExpandableListViewAdapter(getActivity() , dataList);
expandableListView.setAdapter(adapter);
MyUtils.setListViewHeightBasedOnChildren(expandableListView);
expandableListView.setOnGroupClickListener(this);
expandableListView.setOnChildClickListener(this);
In my app,if listview item layout's root view is RelativeLayout,it will cause this crash.Because in api 18 RelativeLayout source code
if(mLayoutParams.width >= 0) {
width = Math.max(width, mLayoutParams.width);
}
and in api >=19 RelativeLayout source code
if(mLayoutParams != null && mLayoutParams.width >= 0) {
width = Math.max(width, mLayoutParams.width);
}
the mLayoutParams maybe null if you inflate item view in this method:
contentView = (ViewGroup) LayoutInflater.
rom(context).inflate(R.layout.select_text_oprate_window, null);
So,you can use this method:
contentView = (ViewGroup)
LayoutInflater.from(context).inflate(R.layout.select_text_oprate_window, parent,false);
Also you can change item layout's root view to LinearLayout.

Android popup won't dismiss

I am trying to implement a popup in my application but it won't dismiss. The Popup is supposed to open when I click on a Plus button, and this works. However, it is supposed to close when I click on the Cancel button in popup layout but it doesn't. why?
Popup layout (tempo_popup.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" >
<requestFocus />
</EditText>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1" >
<Button
android:id="#+id/confirmtempo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/Confirm" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1" >
<Button
android:id="#+id/canceltempo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/Cancel" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Java code:
public class MetronomeActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_metronome);
final Button plus = (Button) findViewById(R.id.tempop);
final Button minus = (Button) findViewById(R.id.tempom);
final Button confirm_tempo = (Button) findViewById(R.id.confirmtempo);
plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View pop = inflater.inflate(R.layout.tempo_popup, null, false);
final PopupWindow pw = new PopupWindow(
inflater.inflate(R.layout.tempo_popup, null, false),
250, 150, true);
// The code below assumes that the root container has an id called 'main'
pw.showAtLocation(plus, Gravity.CENTER, 0, 0);
Button cancel_tempo = (Button) pop.findViewById(R.id.canceltempo);
cancel_tempo.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("Begin1", "POPUP CANCEL");
pw.dismiss();
}
});
}
});
}
}
Damn it! Replace single line of code, it will work like charm.
Instead:
PopupWindow popUpWindow = new PopupWindow(inflater.inflate(R.layout.tempo_popup, null, false),250, 150, true);
Use:
View view = inflater.inflate(R.layout.tempo_popup, null, false);
PopupWindow popUpWindow = new PopupWindow(view, 250, 150, true);
Does the Popup cancel log get printed? Otherwise this might help:
Android popup window dismissal

Resources