我有一个问题,我不知道如何找到它来解决它。有一个网站模板,块上有很多动画,当你开始滚动页面时,会出现类似的效果,好像页面正在尝试适应当前屏幕。
Segrei Ulanov's questions
我有一个与 AT 命令通信的 sim800l 设备。AT+SAPBR=3,1,"CONTYPE","GPRS";
循环函数接受和处理,还将模块的响应显示到控制台。
void loop()
{
if (Serial3.available()){
Serial.write(Serial3.read());
}
if (Serial.available()){
Serial3.write(Serial.read());
}
}
通过发出 AT 命令AT+SAPBR=3,1,"CONTYPE","GPRS";
,我得到 OK 或 ERROR 响应。
我想用条件 if 语句处理响应。
我在互联网上找到了答案,但它们对我不起作用。
int x;
String str;
void loop()
{
if(Serial.available() > 0)
{
str = Serial.readStringUntil('\n');
x = Serial.parseInt();
}
}
我在网上看到你可以使用这些函数来确定答案。
String sendATCommand(String cmd, bool waiting) {
String _resp = ""; // Переменная для хранения результата
Serial.println(cmd); // Дублируем команду в монитор порта
SIM800.println(cmd); // Отправляем команду модулю
if (waiting) { // Если необходимо дождаться ответа...
_resp = waitResponse(); // ... ждем, когда будет передан ответ
// Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
if (_resp.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду
_resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
}
Serial.println(_resp); // Дублируем ответ в монитор порта
}
return _resp; // Возвращаем результат. Пусто, если проблема
}
String waitResponse() { // Функция ожидания ответа и возврата полученного результата
String _resp = ""; // Переменная для хранения результата
long _timeout = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд)
while (!SIM800.available() && millis() < _timeout) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
if (SIM800.available()) { // Если есть, что считывать...
_resp = SIM800.readString(); // ... считываем и запоминаем
}
else { // Если пришел таймаут, то...
Serial.println("Timeout..."); // ... оповещаем об этом и...
}
return _resp; // ... возвращаем результат. Пусто, если проблема
}
在 Canvas 中,我画了一个正方形并在角落放置了圆圈,它们用作按钮,您可以使用拖放来调整形状的大小。
如果我指定了底角的坐标x1
, y2
,那么我第一次触摸就很难进去了,那么我需要一个如图所示的框架,条件是如果触摸在框架内,你可以调整大小.
但是如何实现呢?我想出了这个主意,但在我看来吃起来更容易。
if ((x > x1-max && x < x1+max && y > y2-max && y < y2+max) && touchActive) {
x1 = event!!.x
touchActive = false
invalidate()
} else{
touchActive = true
}
看了这段代码,你想了很久,如果我需要重做逻辑,我需要添加这么多条件,以至于我总是无法记住它。
添加了一个答案。
class ExampleRect(context: Context, att : AttributeSet) : View(context, att) {
private val rect : RectF = RectF()
val p = Paint().apply {
color = Color.DKGRAY
strokeWidth = 10f
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
rect.set(400f, 40f, 40f, 400f)
canvas?.apply {
drawRect(rect, p)
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
println("click -> ${rect.contains(event!!.x, event.y)}")
return true
}
}
这就是发生的事情。
我正在使用 Google的类参考RecyclerViewFragment
示例 这个示例使用静态数据
private fun initDataset() {
dataset = Array(DATASET_COUNT, {i -> "This is element # $i"})
}
我将来自服务器的数据延迟连接到此示例,因此它 recyclerView.adapter = CustomAdapter(dataset)
可以提前工作。
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.recycler_view_frag,
container, false).apply { tag = TAG}
recyclerView = rootView.findViewById(R.id.recyclerView)
// LinearLayoutManager is used here, this will layout the elements in a similar fashion
// to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
// elements are laid out.
layoutManager = LinearLayoutManager(activity)
currentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER
if (savedInstanceState != null) {
// Restore saved layout manager type.
currentLayoutManagerType = savedInstanceState
.getSerializable(KEY_LAYOUT_MANAGER) as LayoutManagerType
}
setRecyclerViewLayoutManager(currentLayoutManagerType)
// Set CustomAdapter as the adapter for RecyclerView.
recyclerView.adapter = CustomAdapter(dataset)
return rootView
}
这就是我所做的
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
mDownloadInformationFromTheServerNews.initWorkingWithData(object : DownloadInformationFromTheServerNews.WorkingWithData{
override fun getData(list: ArrayList<ArticlesList>) {
DATASET_COUNT = list.size
lists.addAll(list)
positions += 30
val handler = android.os.Handler()
handler.postDelayed({
remove() /Как только данные пришли, сообщаю адаптеру.
}, 2000)
}
})
remove() // Если это не сделаю, старые данные не увижу, которые
// отображаются после переворота экрана
return rootView
}
这就是我得到的。为什么会这样?
一旦我翻转屏幕,第二个方法调用就会触发remove()
,我会看到之前保存的位置,但是一旦remove()
调用第一个列表,它就会返回到第一个位置。
如果您删除第二个呼叫remove()
,那么我将看不到保存的位置,而只会在计时器到期后返回到第一个位置。
如果您删除计时器中的第一个remove()
,一切都会好起来的,但这是您需要报告数组中的数据已更新的方式。否则,第一次启动时,数据不会显示,需要将手机翻过来。
翻转屏幕时,我在重新创建活动时遇到问题。Dagger 2 每次都会为演示者提供一个新链接,我需要它来保存或至少在第一次启动后使用之前创建的指向演示者的链接。
我需要这个来保存、恢复 RecyclerView 状态。
现在我保存了,不是很方便。
class ArticlesActivity : AppCompatActivity(), ViewArticles {
@Inject lateinit var presenter: PresenterImpl
private lateinit var viewAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>
private lateinit var viewManager: RecyclerView.LayoutManager
private lateinit var search : EditText
private lateinit var recyclerView: RecyclerView
private lateinit var progressBar : ProgressBar
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_articles)
if(presenterImpl == null) {
presenterImpl = presenter // 1 кэширую ссылку
presenterImpl!!.getData(0, "")
}else{
presenterImpl!!.onConfigurationChanged(this)
}
//...
}
companion object {
private val TAG = "ArticlesActivity"
private var presenterImpl: PresenterImpl? = null //2. СЮДА
}
}
这里需要将接收到的链接缓存在companion中,翻屏后查看。有用。但在这里我保留了两个到 Presenter 的链接。
在 stackoverflow ( link ) 上找到了一种保存 RecyclerView 状态的方法。保存发生,但屏幕旋转后没有恢复。
在gif的最后可以看到,在旋转之后,我调用了数据加载方法,调用了RecyclerView方法来更新列表。如果我不这样做,我会得到一个白屏。
以前,我做的不一样。保存数组和滚动位置。
class BookmarkActivity : AppCompatActivity(), ViewBookmark{
private lateinit var viewAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>
private lateinit var viewManager: RecyclerView.LayoutManager
private lateinit var recyclerView: RecyclerView
private val presenter : PresenterBookmark
private val arrayList: ArrayList<BookmarkList>
private lateinit var progressBar : ProgressBar
companion object {
val TAG = "BookmarkActivity"
val LIST_STATE_KEY = "bookmark_list"
}
init {
arrayList = ArrayList()
presenter = PresenterImpl(this)
}
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_bookmark)
progressBar = findViewById(R.id.progressBarBookmark)
recyclerView = findViewById<RecyclerView>(R.id.rv_bookmark)
viewManager = LinearLayoutManager(this)
viewAdapter = BookmarkAdapter(this)
recyclerView.apply {
layoutManager = viewManager
adapter = viewAdapter
}
if(savedInstanceState == null){
presenter.getData()
removeList()
}
}
override fun getRepositoriesRowsCount(): Int = presenter.getSizeData()
override fun currentListPosition(position: Int): Int = presenter.setCurrentListPosition(position)
override fun getItemViewHolder(rowView: ItemViewHolder, position: Int) = presenter.setItemViewHolder(rowView, position)
override fun progressBarGone() {
progressBar.visibility = View.GONE
}
override fun removeList() {
recyclerView.adapter.notifyDataSetChanged()
}
override fun stopScroll() {
recyclerView.stopScroll()
}
public override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
Log.d("onSaveInstanceState", "Save -----")
outState!!.putParcelable(LIST_STATE_KEY, recyclerView.getLayoutManager().onSaveInstanceState());
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
if (savedInstanceState != null) {
Log.d("onRestoreInstanceState", "Restore YES-----")
val savedRecyclerLayoutState : Parcelable = savedInstanceState.getParcelable(LIST_STATE_KEY)
recyclerView.layoutManager.onRestoreInstanceState(savedRecyclerLayoutState)
progressBarGone()
presenter.getData() // ЗАГРУЖАЮ ДАННЫЕ СНОВА
removeList() //ВЫЗЫВАЮ recyclerView.adapter.notifyDataSetChanged()
}
}
}
下午好,我有RecyclerView
这种类型的适配器
class ListNewsAdapter(val listNewsArrayList: ArrayList<ListNews>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
var title: TextView
init {
title = v.findViewById(R.id.titles)
}
}
//Класс который во время загрузки отображает програсс бар
class ShowProgressBar(v: View) : RecyclerView.ViewHolder(v) {
lateinit var mProgressBar: ProgressBar
init {
//Бывает что mProgressBar не успевает проинициализироваться
try {
mProgressBar = v.findViewById(R.id.progressBar)
} catch (e : ExceptionInInitializerError){
Log.d(TAG, e.toString())
}
}
fun progressBarHide() {
Log.d(TAG, "Если нечего получить, мы скрываем прогресс бар...")
mProgressBar.visibility = View.GONE
}
}
}
启动适配器后,我需要将 ShowProgressBar 和 ViewHolder 类引用传递给 Fragment。怎么做?
拥有一个生成 json 作为响应的主机。
http://example.com/get-json/getJsonPosts.php?2
其中 2 是帖子 ID。
我无法@Get
传递参数。
interface Api {
@GET("getJsonPosts.php?{id}")
fun loadtPost(@Path("id") groupId: Int): Observable<ArrayList<Card>>
}
执行
override fun uploadData() {
var api : Api? = null
api = MyApplication().connectServer()
api!!.loadtPost(10) // Передаю параметр
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ e ->
recyclerView.adapter!!.notifyItemInserted(cards.size - 1)
for (i in 0 until e.size) {
cards.add(Card(e[i].photoUrl,
e[i].title,
e[i].date,
e[i].description,
e[i].photoUrl,
e[i].likeCaunt))
}
})
}
我收到一个错误
java.lang.IllegalArgumentException: URL query string "{id}" must not have replace block. For dynamic query parameters use @Query.
我现在正在尝试这个
API {
@GET("getJsonPosts.php?")
fun loadtPost(@Query("") groupId: Int): Observable<ArrayList<Card>>
}
我收到一个错误
io.reactivex.exceptions.OnErrorNotImplementedException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $
也许我需要像这样实现请求:
http://example.com/get-json/getJsonPosts.php?id=2
我正在躲起来学习 Dagger 2,理论上这似乎并不难,但实际上我已经花了 2 天时间让项目启动并运行,但没有任何结果。
@Module
class ActivityModule {
@Provides
@NonNull
@Singleton
fun getActivitys() : TestClass = TestClass()
}
@Module
class AppModule(val context: Context) {
@Provides
@Singleton
fun getContexts() : Context = context
}
@Component(modules = [(ActivityModule::class), (AppModule::class)])
@Singleton
interface AppComponent {
fun inject(mainActivity: MainActivity)
}
应用程序
class App : Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = buildComponent()
}
fun getComponent() : AppComponent = appComponent
private fun buildComponent(): AppComponent {
return DaggerAppComponent.builder()
.appModule(AppModule(this))
.activityBindgsModule(ActivityModule())
.build()
}
}
主要活动
class MainActivity : AppCompatActivity() {
@Inject lateinit var testClass: TestClass
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
App().getComponent().inject(this)
Log.d("MAIN", testClass.getString())
}
}
我在清单上写了
<application
android:name=".App"
...
我在 Build 中注册了这样的依赖项,尝试更新,它没有帮助。
compile "com.google.dagger:dagger:2.11"
compile "com.google.dagger:dagger-android:2.11"
compile "com.google.dagger:dagger-android-support:2.11"
kapt "com.google.dagger:dagger-compiler:2.11"
kapt "com.google.dagger:dagger-android-processor:2.11"
当我在模拟器上运行项目时,在构建期间我在 Messenger 部分收到错误
Error:(25, 17) Unresolved reference: DaggerAppComponent
Error:Execution failed for task ':app:compileDebugKotlin'.
> Compilation error. See log for more details
但是如果我从 GitHub 链接下载一个现成的示例到这个项目,一切都会编译,但是一旦我开始一个新项目,我就会出错。我写的这个例子将再写一篇文章。
更新
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 26
defaultConfig {
applicationId "info.android_developer_community.dagerss"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation "com.google.dagger:dagger:2.14"
implementation "com.google.dagger:dagger-android:2.14"
implementation "com.google.dagger:dagger-android-support:2.14"
kapt "com.google.dagger:dagger-android-processor:2.14"
kapt "com.google.dagger:dagger-compiler:2.14"
kapt "com.google.dagger:dagger-android-support:2.14"
}
我想在当前活动中使用对话框,但事实是这个类已经有一个 YouTubeBaseActivity 后继者,因此dialog.show(getSupportFragmentManager()
,“自定义”方法拒绝工作;即,getFragmentManager()
他要求有一个图书馆import android.support.v7.app.AppCompatActivity;
有没有可能以某种方式解决这个问题?
public class PlayVideoYouTube extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener {
private TextView textView3;
private String a;
private YouTubePlayer player;
private static final int RECOVERY_REQUEST = 1;
private YouTubePlayerView youTubeView;
private FragmentManager supportFragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_video_youtube);
youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
youTubeView.initialize(Config.YOUTUBE_API_KEY, this);
}
@Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
this.player = player;
if (!wasRestored) {
player.cueVideo("RJmZBs4MDqU"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
a = String.valueOf(player.getCurrentTimeMillis()); //Получаем текущее время
}
}
@Override
public void onInitializationFailure(Provider provider, YouTubeInitializationResult errorReason) {
if (errorReason.isUserRecoverableError()) {
errorReason.getErrorDialog(this, RECOVERY_REQUEST).show();
} else {
String error = String.format(getString(R.string.player_error), errorReason.toString());
Toast.makeText(this, error, Toast.LENGTH_LONG).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECOVERY_REQUEST) {
// Retry initialization if user performed a recovery action
getYouTubePlayerProvider().initialize(Config.YOUTUBE_API_KEY, this);
}
}
protected Provider getYouTubePlayerProvider() {
return youTubeView;
}
public void rezult(View v) {
textView3 = (TextView) findViewById(R.id.textT);
a =String.valueOf(((float) player.getCurrentTimeMillis() / 1000.0) / 60.0);
textView3.setText(a);
//4. Создаем всплывающий Toast с текстом нажатого элемента
String language = ((TextView) v).getText().toString();
Toast.makeText(this, language, Toast.LENGTH_LONG).show();
CustomDialogFragment dialog = new CustomDialogFragment();
Bundle args = new Bundle();
args.putString("phone", "Передача данных....");
dialog.setArguments(args);
dialog.show(getSupportFragmentManager(), "custom");
^^//Ошибка Cannot resolve method 'getSupportFragmentManager()
}
}