我正在學習 android 編程并且為了練習我正在嘗試為一些直流電機做一個控制器,然后我做了一個 customview 來制作一個虛擬手柄,它使用一個介面和一個回呼叫于 ontouch 偵聽器。
問題是,我正在使用單個 MainActivity 作為導航主機來開發我的應用程式,然后我正在瀏覽不同的片段,我的自定義視圖僅在我覆寫 MainActivity 上的介面方法時才有效,但我無法使其適用我的片段,我想在其中處理手柄的所有邏輯。
我進行了幾天的研究,但我發現的大多數帖子都是用 Java 撰寫的,我無法讓它在 Kotlin 上運行。
我的自定義視圖類
class KanJoypadView: SurfaceView, SurfaceHolder.Callback, View.OnTouchListener{
...kotlin
var joypadCallback: JoypadListener? = null
//the main constructor for the class
constructor(context: Context): super(context){
...
getHolder().addCallback(this)
setOnTouchListener(this)
...
}
//the interface for the main functionally of the view
interface JoypadListener {
fun onJoypadMove(x: Float, y: Float, src: Int){}
}
...
}
我的主要活動
class NavActivity : AppCompatActivity(), KanJoypadView.joypadListener {
...
//Overriding the Function from the interface,
//I just did this for debguging, but I dont want this override here
override fun onJoypadMove(x: Float, y: Float, src: Int) {
Log.d(src.toString(), y.toString()) //** I wanna do this in my Fragment, not in my activity **
}
}
我的片段
class JoystickFragment : Fragment(), KanJoypadView.joypadListener {
...
var enginesArray = arrayOf(0.toFloat(), 0.toFloat(), 0.toFloat(), 0.toFloat())
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
...
val binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_joystick, container, false
)
binding.leftJoypad.joypadCallback = (container?.context as KanJoypadView.JoypadListener?)
lJoypad = binding.leftJoypad.id
}
/*what I really want to do, but it is not happening as it is just happenning the
override from the NavActivity, which I dont need, and not from here which I need*/
override fun onJoypadMove(x: Float, y: Float, src: Int) {
if (src == lJoypad) {
if (y >= 0) {
enginesArray[0] = 1.toFloat()
enginesArray[1] = y
} else if (y < 0) {
enginesArray[0] = 0.toFloat()
enginesArray[1] = y
}
if (src == rJoypad) {
if (y >= 0) {
enginesArray[0] = 1.toFloat()
enginesArray[1] = y
} else if (yAxis < 0) {
enginesArray[0] = 0.toFloat()
enginesArray[1] = y
}
Log.d("Engines array", enginesArray.toString())
}
}
}
}
我還嘗試在片段中創建一個函式,然后從 Activity 的 onMoveJoypad 方法呼叫該函式,但我也無法使其作業。我將不勝感激有關如何實作此功能的任何幫助或建議,在此先感謝!
uj5u.com熱心網友回復:
這:
if (context is joypadListener){
是一種獲取聽眾參考的非常hacky且容易出錯的方法。這也是非常有限的,因為它使得偵聽器不可能是創建視圖的 Activity 之外的任何東西。不要這樣做!
您已經有一個手柄監聽器屬性。只需洗掉private關鍵字,以便任何類都可以從外部設定它想要的任何偵聽器。洗掉整個 try/catch 塊。當需要呼叫偵聽器的函式時,請使用 null 安全?.呼叫來執行此操作,以便在尚未設定回呼的情況下優雅地不執行任何操作。
旁注:按照慣例,所有類和介面名稱都應以大寫字母開頭。如果您不遵守此約定,您的代碼將變得非常難以閱讀和解釋。
另外,我建議您避免使用使類實作介面的模式,以作為它正在操作的物件之一或它自己的內部函式的回呼。您在上面的代碼中這樣做了兩次。您的自定義視圖為其自己的觸摸偵聽器執行此操作,而您的 Activity 執行此操作以充當游戲板偵聽器。
原因是它公開暴露了類的內部功能并降低了模塊化。它會使單元測驗更加困難。它不必要地暴露了濫用您設計的類的方法。對活動來說,這樣做并不是什么大不了的事,因為無論如何你很少使用外部的活動實體。但是視圖類這樣做很難看。
另一種方法是將介面實作為匿名物件或 lambda,以便對外部類隱藏回呼的功能。
編輯:如何在您的片段中執行此操作
如果你想聽從我上面的建議,不要在你的類中實作回呼介面。請改用 lambda 或匿名類。
class JoystickFragment : Fragment() {
//...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//...
adapter.joypadCallback = joypadListener
//...
}
private val joypadListener = KanJoypadView.JoypadListener { x, y, src ->
if (src == lJoypad) {
if (y >= 0) {
enginesArray[0] = 1.toFloat()
enginesArray[1] = y
} else if (y < 0) {
enginesArray[0] = 0.toFloat()
enginesArray[1] = y
}
if (src == rJoypad) {
if (y >= 0) {
enginesArray[0] = 1.toFloat()
enginesArray[1] = y
} else if (yAxis < 0) {
enginesArray[0] = 0.toFloat()
enginesArray[1] = y
}
Log.d("Engines array", enginesArray.toString())
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/429605.html
上一篇:在React中單擊時狀態未更新
