Providing click method to widgets - android-studio

I tried to create a widget and I succeeded, but how can I meet the click needs of the tools in the widget?
What I'm talking about is not redirecting onto an activity, I'm looking for a method where I can create a function.
The layout file used for the widget below
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:id="#+id/kare"
android:theme = "#style/Theme.Mytwo.AppWidgetContainer" >
<Button
android:id = "#+id/appwidget_text"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_centerInParent = "true"
android:background = "#048018"
android:text = "clean"
android:textSize = "24sp"
android:padding="15dp"
android:textStyle = "bold" />
</RelativeLayout >
This is my widget provider class
class NewAppWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { // There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.new_app_widget )
appWidgetManager.updateAppWidget(appWidgetId, views)
}
And finally my provider info file
<appwidget-provider xmlns:android = "http://schemas.android.com/apk/res/android"
android:description = "#string/app_widget_description"
android:initialKeyguardLayout = "#layout/new_app_widget"
android:initialLayout = "#layout/new_app_widget"
android:minWidth = "100dp"
android:minHeight = "40dp"
android:previewImage = "#drawable/ic_launcher_foreground"
android:previewLayout = "#layout/new_app_widget"
android:resizeMode = "horizontal|vertical"
android:targetCellWidth = "2"
android:targetCellHeight = "2"
android:updatePeriodMillis = "86400000"
android:widgetCategory = "home_screen" />

I'm not sure what you mean by "create a function". The only way to get something to happen when a widget is clicked is via RemoteViews#setOnCheckedChangeResponse or RemoteViews#setOnClickFillInIntent or
RemoteViews#setOnClickPendingIntent or
RemoteViews#setOnClickResponse.
Apart from calling RemoteViews.RemoteResponse#addSharedElement,
all that any of these can do is to send out an Intent, which can start an Activity or awaken a BroadcastReceiver.
You can't execute your own code inside the widget: any code that you want to execute in response to a click on a widget has to be in the Activity or the BroadcastReceiver. It doesn't have to be an Activity or a BroadcastReceiver inside the app that created the widget, although it usually will be.
Since the RemoteViews is created inside your app's AppWidgetProvider#updateAppWidget, you can put the appWidgetId as an extra into the PendingIntent, so you can tell which widget was clicked.

Related

How can I collapse and expand the recycler view layout when the button is clicked?

I am developing a recycler view with Kotlin. Let's look at my code, when I click on the orderProduct button, the orderRecyclerview is visible and on the contrary, when I click again, the visible is gone. But sometimes when I click on it, the recycler view is shown and sometimes it is not shown.
So how can I do this anytime? How can I solve this bug?
orderProduct.setOnClickListener{
orderProduct.setCompoundDrawablesWithIntrinsicBounds(0, 0, if (!isClicked) R.drawable.btn_down else R.drawable.btn_up, 0)
if (isClicked) {
var r = Runnable {
try {
orderRecyclerview.visibility=View.VISIBLE
paymentList= paymentDb?.paymentDao()?.getAll()!!
mAdapter = PaymentRecylcerViewAdapter(this, paymentList)
mAdapter.notifyDataSetChanged()
orderRecyclerview.adapter = mAdapter
orderRecyclerview.layoutManager = LinearLayoutManager(this)
orderRecyclerview.setHasFixedSize(false)
}catch (e: Exception) {
}
}
val thread = Thread(r)
thread.start()
}else {
orderRecyclerview.visibility=View.GONE
}
isClicked = !isClicked
}
Firstly, you can move this code above the onclickListner.
paymentList= paymentDb?.paymentDao()?.getAll()!!
mAdapter = PaymentRecylcerViewAdapter(this, paymentList)
mAdapter.notifyDataSetChanged()
orderRecyclerview.adapter = mAdapter
orderRecyclerview.layoutManager = LinearLayoutManager(this)
orderRecyclerview.setHasFixedSize(false)
Then inside the onClickListner handle visibility of orderRecyclerview.
For better user experience, You can also add animation in this.
Hope, it will help.
add Dependecy
compile 'net.cachapa.expandablelayout:expandablelayout:2.9.2'
<net.cachapa.expandablelayout.ExpandableLayout
android:id="#+id/expandable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:el_duration="1000"
app:el_expanded="true"
app:el_parallax="0.5">
<RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Fixed height" />
To trigger the animation, simply grab a reference to the ExpandableLayout from your Java code and and call either of expand(), collapse() or toggle().

Xamarin.Forms Action Bar - Center Aligned Image

Using Xamarin.Forms, how do I get the same effect as the application pictured below, specifically to show a centred image on the Action Bar / page tool bar (the section in a blue box)?
I would like to have a long width image in that section, and the solution must work for Android, iOS, Windows Phone, and Universal Windows (even if it means writing custom renderers or platform specific xamarin code).
I suggest you create your own Xamarin.Forms view and handle the navigation by yourself something similar to this:
public class CustomBackNavigationBar : StackLayout
{
public Image BackIcon;
public Image Icon;
public Label IconTitle;
public StackLayout IconContainer;
public CustomBackNavigationBar(string title, string icon)
{
Padding = new Thickness(15,5);
HeightRequest = 40;
Orientation = StackOrientation.Horizontal;
VerticalOptions = LayoutOptions.Start;
BackgroundColor = StaticData.BlueColor;
Spacing = 15;
BackIcon = new Image
{
Source = StaticData.BackIcon,
HorizontalOptions = LayoutOptions.Start
};
Label Title = new Label
{
Text = title,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
FontAttributes = FontAttributes.Bold,
VerticalTextAlignment = TextAlignment.Center
};
Icon = new Image
{
Source = icon
};
IconTitle = new Label
{
Text = StaticData.CallAgent,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
};
IconContainer = new StackLayout
{
HorizontalOptions = LayoutOptions.EndAndExpand,
Spacing = 2,
Children = { Icon, IconTitle }
};
Children.Add(BackIcon);
Children.Add(Title);
Children.Add(IconContainer);
#region Events
BackIcon.GestureRecognizers.Clear();
BackIcon.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(PopAsync)
});
#endregion
}
async void PopAsync()
{
await App.AppNavigation.PopAsync();
}
}

tint2 ToolbarItem/Button size

I'm using Tint2 to create a desktop application. I want to use the native toolbar capability, button when I add a ToolbarItem (docs) to the toolbar, it simply doesn't show up:
var toolbar = new Toolbar();
var new_button = new ToolbarItem();
new_button.title = 'Hello';
new_button.enabled = true;
toolbar.appendChild(new_button);
win.toolbar = toolbar;
Similarly, I tried just using a Button (docs) instead of a ToolbarItem (the latter is recommended in the docs). This results in a very small button - the width property is ignored:
var toolbar = new Toolbar();
var new_button = new Button();
new_button.title = 'Hello';
new_button.width = '150px';
toolbar.appendChild(new_button);
win.toolbar = toolbar;
If you notice on the Toolbar class that there's a property called 'state', it sets what type of display the toolbar uses. Users can set various preferences as to whether they want to see images, labels or images or labels.
My guess is its default is "image only" and the label isn't used.
var toolbar = new Toolbar();
var new_button = new ToolbarItem();
new_button.title = 'Hello';
new_button.width = '150px';
toolbar.state = 'label'; // THIS LINE IS IMPORTANT FOR NO IMAGE TOOLBARS.
toolbar.appendChild(new_button);
win.toolbar = toolbar;
The second issue you're seeing is the toolbar dictating the width of something. Using your own width may or may not be respected on the toolbar. You can always just place the button directly within the window and skip the toolbar entirely.
var new_button = new Button();
new_button.title = 'Hello';
new_button.width = '150px';
new_button.left = '20px';
new_button.top = '20px';
win.appendChild(new_button);

MonoTouch Message Element opes page with string elements

I have the following code:
Section _section = new Section ("Test");
foreach (ExampleData data in Example.data) {
MessageElement Item = new MessageElement (){
Sender = data.Name,
Subject = data.Value,
Body = data.Description,
Date = data.Modified
} ;
_section.Add(Item);
var root = new RootElement("Item Expanded"){
new Section ("test2"){
new StringElement("Field Name", data.FieldName),
new StringElement("Value", data.Value),
new StringElement("Description", data.Description)
}
} ;
_section.Add(root);
} ;
var _rootElement = new RootElement ("Items") {
_section
} ;
I would like this to work in such a way that when a Message Element is tapped it shows the section with ("test2") that has the same data (e.g. the data was added during the same run of the loop.) I realize this will not happen currently, as it seems the Message Element
requires an Action delegate to do anything on a tap event, plus I'm adding everything to the same section. However, is there any way to replicate the behavior of multiple nested root elements and sections with a Message Element? If I create new pages/screens and try to transition that way, it rests the navigation controller and I lose the use of the back button, even if "push" is set to true.
Not sure what you want exactly. Replace your "Item Expanded" root element code with this to push a dialog viewcontoller on the navigation stack with a backbutton. Ofcourse your DialogViewcontroller should be in a UINavigation controller in the first place for this to work
Item.Tapped += delegate(DialogViewController arg1, UITableView arg2, NSIndexPath arg3)
{
var newDialogVC = new DialogViewController(
UITableViewStyle.Grouped,
new RootElement("Item Expanded")
{
new Section ("test2"){
new StringElement("Field Name", "test"),
new StringElement("Value", "test"),
new StringElement("Description", "test")
}
}
, true);
arg1.NavigationController.PushViewController(newDialogVC,true);
};

Why is UILabel not updating?

I have created a view that shows lost connection messages to users which pops over the current view. I want to update the view periodically based on connection status changes.
I can properly get the view and change the text of a label (verified with WriteLines), but nothing changes on the actual display. I even tried removing the view and readding it and calling SetNeedsDisplay, but nothing seems to help.
I have a global variable called OverView:
public static UIView OverView;
I create the label subview, add it to the overview and pop the overview in front of the current view:
UILabel labelTitle = new UILabel();
labelTitle.Text = title;
UIView labelTitleView = (UIView) labelTitle;
labelTitleView.Tag = 5000;
OverView.AddSubview(labelTitleView);
curView.InsertSubviewAbove(OverView, curView);
curView.BringSubviewToFront(OverView);
And then at a later time, I try to modify it like this from another function:
if ((OverView != null) && (OverView.Subviews != null))
{
for (int i = 0; i < OverView.Subviews.Length; i++)
{
WriteToConsole("Type: " + OverView.Subviews[i].GetType());
if (OverView.Subviews[i] is UILabel)
{
WriteToConsole("Found Label with Tag: " + ((UILabel)(OverView.Subviews[i])).Tag + " Text: " + ((UILabel)(OverView.Subviews[i])).Text);
if (((UILabel)(OverView.Subviews[i])).Tag == 5000)
{
WriteToConsole("Setting subview Title to: " + lostConnectionTitle);
lock (overViewLocker)
{
appReference.InvokeOnMainThread(delegate
{
UILabel tempLabel = ((UILabel)(OverView.Subviews[i]));
tempLabel.Text = lostConnectionTitle;
OverView.Subviews[i].RemoveFromSuperview();
OverView.AddSubview(tempLabel);
OverView.BringSubviewToFront(tempLabel);
OverView.SetNeedsLayout();
OverView.SetNeedsDisplay();
WriteToConsole("SetNeedsDisplay");
});
}
}
}
}
}
Have you tried to use delegate methods on your label, and change their value when events occur ?
For example, if your event is clicking on a button, you should have something like that:
yourLabel.Text = "Init";
buttonExample.TouchUpInside += (sender, e) => {
yourLabel.Text = "I touched my button";
};
When your View loads, you'll see "Init" and your button and once you click on it, the label text changed.
Xamarin has some explanation about events and delegate methods here.
I hope that helped.

Resources