onMessage()
openLink
function onMessage(e) { var bot = e.message.annotations[0].userMention.user.displayName; var loc = encodeURI(e.message.text.substring(bot.length+2)); var mapClick = { "openLink": { "url": "https://google.com/maps/search/?api=1&query=" + loc } }; return { // see JSON payload in the documentation link above }; }
gcloud beta compute ssl-policies create web-front-end-app-policy \ --profile MODERN --min-tls-version 1.1
gcloud beta compute target-https-proxies update my_https_lb \ --ssl-policy my_ssl_policy
Os aplicativos desenvolvidos com o Flutter apresentam qualidade, desempenho e designs personalizados em diversas plataformas. O Flutter beta também funciona com a versão pré-lançamento do Dart 2, que oferece maior suporte à declaração de IU no código com um mínimo de linhas de código. Por exemplo, o Dart 2 infere new e const para remover código padrão (boilerplate) durante a criação da IU. Vejamos um exemplo:
// Before Dart 2 Widget build(BuildContext context) { return new Container( height: 56.0, padding: const EdgeInsets.symmetric(horizontal: 8.0), decoration: new BoxDecoration(color: Colors.blue[500]), child: new Row( ... ), ); } // After Dart 2 Widget build(BuildContext context) => Container( height: 56.0, padding: EdgeInsets.symmetric(horizontal: 8.0), decoration: BoxDecoration(color: Colors.blue[500]), child: Row( ... ), );
widget.dart no GitHub É ótimo ver o crescimento do ecossistema do Flutter. Hoje, mais de 1.000 pacotes trabalham com o Flutter (por exemplo: SQLite, Firebase, Facebook Connect, preferências compartilhadas, GraphQL e muitos outros), temos mais de 1.700 pessoas do nosso chat e estamos muito orgulhosos de ver a nossa comunidade lançar sites novos, como o Flutter Institute, o Start Flutter e o Flutter Rocks. Além disso, você já pode se inscrever na nova newsletter Flutter Weekly, editada e publicada pela nossa comunidade. Enquanto esperamos a versão 1.0, estamos trabalhando na estabilização e na finalização do cenário. Hoje, nosso roteiro (muito influenciado pela comunidade) monitora recursos como facilitar a integração do Flutter em um aplicativo, WebView em linha, melhores APIs de rotas e navegação, maior suporte ao Firebase, mapas em linha, mecanismo básico reduzido e muito mais. Queremos lançar novos betas mais ou menos a cada quatro semanas. Recomendamos que você vote (👍) em aspectos importantes para você e seu aplicativo em nosso rastreador de falhas. Agora é o momento perfeito para usar o Flutter. Você pode começar do zero e criar rapidamente o seu primeiro aplicativo funcional do Flutter usando o nosso guia de primeiros passos. Se você já tem o Flutter instalado, acesse o canal beta seguindo estas instruções. Queremos agradecer de coração seu apoio, seu feedback e muitas outras contribuições. Esperamos poder continuar essa jornada com todos (e estamos ansiosos para ver o que vocês estão criando)! Alô, desenvolvedores da China! Essa postagem também está disponível em chinês.
--create-disk flag
ImageView
A
B
ViewPager
RecyclerView
GridFragment
ImageData
onClick
ImagePagerFragment
ImageFragments
MainActivity
transitionName
ImageFragment
setTransitionName
onCreateView
SharedElementCallbacks
onMapSharedElements
FragmentManager
fragment.getFragmentManager() .beginTransaction() .setReorderingAllowed(true) // setAllowOptimization before 26.1.0 .addSharedElement(imageView, imageView.getTransitionName()) .replace(R.id.fragment_container, new ImagePagerFragment(), ImagePagerFragment.class.getSimpleName()) .addToBackStack(null) .commit();
setReorderingAllowed
true
onCreate(Bundle)
onDestroy()
TransitionSet
<ImagePagerFragment.java>
Transition transition = TransitionInflater.from(getContext()) .inflateTransition(R.transition.image_shared_element_transition); setSharedElementEnterTransition(transition);
<image_shared_element_transition.xml>
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="375" android:interpolator="@android:interpolator/fast_out_slow_in" android:transitionOrdering="together"> <changeClipBounds/> <changeTransform/> <changeBounds/> </transitionSet>
setExitSharedElementCallback()
SharedElementCallback
Fragment
<GridFragment.java>
setExitSharedElementCallback( new SharedElementCallback() { @Override public void onMapSharedElements( List<String> names, Map<String, View> sharedElements) { // Locate the ViewHolder for the clicked position. RecyclerView.ViewHolder selectedViewHolder = recyclerView .findViewHolderForAdapterPosition(MainActivity.currentPosition); if (selectedViewHolder == null || selectedViewHolder.itemView == null) { return; } // Map the first shared element name to the child ImageView. sharedElements .put(names.get(0), selectedViewHolder.itemView.findViewById(R.id.card_image)); } });
setEnterSharedElementCallback()
setEnterSharedElementCallback( new SharedElementCallback() { @Override public void onMapSharedElements( List<String> names, Map<String, View> sharedElements) { // Locate the image view at the primary fragment (the ImageFragment // that is currently visible). To locate the fragment, call // instantiateItem with the selection position. // At this stage, the method will simply return the fragment at the // position and will not create a new one. Fragment currentFragment = (Fragment) viewPager.getAdapter() .instantiateItem(viewPager, MainActivity.currentPosition); View view = currentFragment.getView(); if (view == null) { return; } // Map the first shared element name to the child ImageView. sharedElements.put(names.get(0), view.findViewById(R.id.image)); } });
postponeEnterTransition()
onCreateView()
startPostponedEnterTransition()
postponeEnterTransition
startPostponeEnterTransition
<ImageFragment.java>
Glide.with(this) .load(arguments.getInt(KEY_IMAGE_RES)) // Load the image resource .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { getParentFragment().startPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { getParentFragment().startPostponedEnterTransition(); return false; } }) .into((ImageView) view.findViewById(R.id.image));
setExitTransition(TransitionInflater.from(getContext()) .inflateTransition(R.transition.grid_exit_transition));
<grid_exit_transition.xml>
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="375" android:interpolator="@android:interpolator/fast_out_slow_in" android:startDelay="25"> <fade> <targets android:targetId="@id/card_view"/> </fade> </transitionSet>
GridAdapter
// The 'view' is the card view that was clicked to initiate the transition. ((TransitionSet) fragment.getExitTransition()).excludeTarget(view, true);
onViewCreated
recyclerView.addOnLayoutChangeListener( new OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { recyclerView.removeOnLayoutChangeListener(this); final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); View viewAtPosition = layoutManager.findViewByPosition(MainActivity.currentPosition); // Scroll to position if the view for the current position is null (not // currently part of layout manager children), or it's not completely // visible. if (viewAtPosition == null || layoutManager.isViewPartiallyVisible(viewAtPosition, false, true)){ recyclerView.post(() -> layoutManager.scrollToPosition(MainActivity.currentPosition)); } } });
var registrationToken = 'YOUR_REGISTRATION_TOKEN'; var message = { data: { score: '850', time: '2:45' }, token: registrationToken }; admin.messaging().send(message) .then((response) => { console.log('Successfully sent message:', response); }) .catch((error) => { console.log('Error sending message:', error); });
var registrationTokens = [ 'YOUR_REGISTRATION_TOKEN_1', // ... 'YOUR_REGISTRATION_TOKEN_n' ]; admin.messaging().subscribeToTopic(registrationTokens, topic) .then(function(response) { console.log('Successfully subscribed to topic:', response); }) .catch(function(error) { console.log('Error subscribing to topic:', error); });
Os apps com conteúdo imersivo podem exibir esse conteúdo em tela cheia nos dispositivos com recorte de tela.
Nas notificações com estilo MessagingStyle, você pode mostrar conversas e respostas inteligentes (esquerda) e até anexar imagens e adesivos (direita).
Build.getSerial()